aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--HOWTO/DTRACE.md3
-rw-r--r--bootstrap/bin/start.bootbin5248 -> 5242 bytes
-rw-r--r--bootstrap/bin/start_clean.bootbin5248 -> 5242 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin11576 -> 11576 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_block.beambin14424 -> 14424 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bsm.beambin12256 -> 12488 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_disasm.beambin25028 -> 25028 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_jump.beambin8500 -> 8524 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_utils.beambin13360 -> 13220 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin37168 -> 37580 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_parse.beambin37672 -> 37688 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_expand.beambin16172 -> 15144 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_codegen.beambin51812 -> 51816 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel.beambin43204 -> 43196 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_controller.beambin30844 -> 30848 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code.beambin6960 -> 6916 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code_server.beambin26248 -> 26184 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_1.beambin24908 -> 24908 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_util.beambin10508 -> 10512 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file.beambin14416 -> 14484 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_io_server.beambin14184 -> 14460 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group.beambin11716 -> 11720 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/heart.beambin3888 -> 3952 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/hipe_unified_loader.beambin12716 -> 12716 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin20684 -> 21148 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_dns.beambin19716 -> 19716 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin12824 -> 12936 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.app1
-rw-r--r--bootstrap/lib/kernel/ebin/packages.beambin2244 -> 0 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user.beambin12304 -> 12384 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/base64.beambin4528 -> 4528 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/beam_lib.beambin18044 -> 18044 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/c.beambin13928 -> 13904 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_utils.beambin28824 -> 28820 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v9.beambin50016 -> 50008 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin24152 -> 27204 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin23740 -> 23116 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_expand_records.beambin21880 -> 21652 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin85732 -> 83808 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_parse.beambin71548 -> 69956 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_pp.beambin23304 -> 24640 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_scan.beambin31740 -> 33128 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_tar.beambin15328 -> 15328 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/escript.beambin16996 -> 17264 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/eval_bits.beambin6736 -> 6736 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/file_sorter.beambin30552 -> 30552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filelib.beambin7816 -> 7816 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filename.beambin12456 -> 12436 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io.beambin6600 -> 6784 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib.beambin8760 -> 9200 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_format.beambin11960 -> 12100 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_pretty.beambin12296 -> 13212 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lib.beambin9068 -> 9624 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin7156 -> 7156 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proc_lib.beambin9200 -> 9776 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc.beambin69144 -> 69144 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc_pt.beambin71564 -> 71084 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/re.beambin12760 -> 12752 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell.beambin30604 -> 30320 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor.beambin22904 -> 23004 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode.beambin11584 -> 11584 bytes
-rw-r--r--erts/doc/src/erlang.xml7
-rw-r--r--erts/emulator/beam/bif.tab266
-rw-r--r--erts/emulator/beam/dist.c2
-rw-r--r--erts/emulator/beam/erl_db_util.c2
-rw-r--r--erts/emulator/beam/erl_init.c1
-rw-r--r--erts/emulator/beam/erl_port.h6
-rw-r--r--erts/emulator/beam/erl_port_task.c66
-rw-r--r--erts/emulator/beam/io.c18
-rw-r--r--erts/emulator/hipe/hipe_mkliterals.c97
-rw-r--r--erts/emulator/test/match_spec_SUITE.erl16
-rw-r--r--erts/preloaded/ebin/erlang.beambin92736 -> 92756 bytes
-rw-r--r--erts/preloaded/src/erlang.erl2
-rw-r--r--lib/common_test/doc/src/common_test_app.xml11
-rw-r--r--lib/common_test/doc/src/cover_chapter.xml87
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml43
-rw-r--r--lib/common_test/doc/src/notes.xml50
-rw-r--r--lib/common_test/doc/src/run_test_chapter.xml6
-rw-r--r--lib/common_test/doc/src/write_test_chapter.xml52
-rw-r--r--lib/common_test/src/ct_cover.erl32
-rw-r--r--lib/common_test/src/ct_netconfc.erl6
-rw-r--r--lib/common_test/src/ct_slave.erl28
-rw-r--r--lib/common_test/src/cth_surefire.erl183
-rw-r--r--lib/common_test/test/Makefile3
-rw-r--r--lib/common_test/test/common_test.cover16
-rw-r--r--lib/common_test/test/ct_cover_SUITE.erl53
-rw-r--r--lib/common_test/test/ct_surefire_SUITE.erl351
-rw-r--r--lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl92
-rw-r--r--lib/common_test/test/ct_test_support.erl31
-rw-r--r--lib/compiler/src/compile.erl38
-rw-r--r--lib/compiler/src/core_scan.erl27
-rw-r--r--lib/compiler/src/sys_pre_expand.erl66
-rw-r--r--lib/compiler/test/compilation_SUITE.erl3
-rw-r--r--lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl28
-rw-r--r--lib/compiler/test/compile_SUITE.erl30
-rw-r--r--lib/crypto/c_src/crypto.c58
-rwxr-xr-x[-rw-r--r--]lib/crypto/doc/src/crypto.xml4
-rw-r--r--lib/crypto/src/crypto.erl81
-rw-r--r--lib/crypto/test/crypto_SUITE.erl32
-rw-r--r--lib/debugger/src/dbg_ieval.erl4
-rw-r--r--lib/debugger/src/dbg_ui_trace.erl12
-rw-r--r--lib/debugger/src/dbg_ui_trace_win.erl4
-rw-r--r--lib/debugger/src/dbg_wx_trace.erl12
-rw-r--r--lib/debugger/src/dbg_wx_trace_win.erl4
-rw-r--r--lib/debugger/src/int.erl25
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml8
-rw-r--r--lib/dialyzer/doc/src/dialyzer_chapter.xml6
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl25
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl5
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl5
-rw-r--r--lib/edoc/priv/edoc.dtd4
-rw-r--r--lib/edoc/src/edoc.erl9
-rw-r--r--lib/edoc/src/edoc.hrl6
-rw-r--r--lib/edoc/src/edoc_data.erl3
-rw-r--r--lib/edoc/src/edoc_doclet.erl28
-rw-r--r--lib/edoc/src/edoc_extract.erl16
-rw-r--r--lib/edoc/src/edoc_layout.erl15
-rw-r--r--lib/edoc/src/edoc_lib.erl67
-rw-r--r--lib/edoc/src/edoc_macros.erl4
-rw-r--r--lib/edoc/src/edoc_parser.yrl8
-rw-r--r--lib/edoc/src/edoc_refs.erl19
-rw-r--r--lib/edoc/src/edoc_wiki.erl3
-rw-r--r--lib/erl_docgen/doc/src/doc-build.xml5
-rwxr-xr-xlib/erl_docgen/priv/bin/xml_from_edoc.escript8
-rw-r--r--lib/erl_docgen/priv/fop.xconf45
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf_params.xsl30
-rw-r--r--lib/erl_docgen/src/docgen_edoc_xml_cb.erl37
-rw-r--r--lib/erl_docgen/src/docgen_xmerl_xml_cb.erl28
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE.erl9
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE.erl13
-rw-r--r--lib/erl_interface/test/ei_print_SUITE.erl4
-rw-r--r--lib/et/src/et.erl4
-rw-r--r--lib/eunit/include/eunit.hrl157
-rw-r--r--lib/eunit/src/eunit.erl5
-rw-r--r--lib/eunit/src/eunit_autoexport.erl7
-rw-r--r--lib/eunit/src/eunit_lib.erl5
-rw-r--r--lib/eunit/src/eunit_surefire.erl5
-rw-r--r--lib/gs/contribs/mandel/mandel.erl3
-rw-r--r--lib/gs/src/gstk_editor.erl6
-rw-r--r--lib/hipe/amd64/hipe_amd64_encode.erl10
-rw-r--r--lib/hipe/flow/hipe_dominators.erl6
-rw-r--r--lib/hipe/icode/hipe_icode_mulret.erl14
-rw-r--r--lib/hipe/regalloc/hipe_coalescing_regalloc.erl8
-rw-r--r--lib/hipe/regalloc/hipe_optimistic_regalloc.erl12
-rw-r--r--lib/hipe/regalloc/hipe_reg_worklists.erl6
-rw-r--r--lib/hipe/rtl/hipe_rtl_arith.inc6
-rw-r--r--lib/hipe/rtl/hipe_rtl_mk_switch.erl6
-rw-r--r--lib/hipe/rtl/hipe_rtl_primops.erl6
-rw-r--r--lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl6
-rw-r--r--lib/hipe/rtl/hipe_rtl_ssapre.erl10
-rw-r--r--lib/hipe/ssa/hipe_ssa.inc6
-rw-r--r--lib/hipe/x86/hipe_x86_assemble.erl4
-rw-r--r--lib/hipe/x86/hipe_x86_postpass.erl8
-rw-r--r--lib/hipe/x86/hipe_x86_ra_postconditions.erl4
-rw-r--r--lib/inets/doc/src/http_uri.xml5
-rw-r--r--lib/jinterface/test/nc_SUITE.erl7
-rw-r--r--lib/kernel/doc/src/Makefile1
-rw-r--r--lib/kernel/doc/src/file.xml28
-rw-r--r--lib/kernel/doc/src/inet.xml5
-rw-r--r--lib/kernel/src/Makefile1
-rw-r--r--lib/kernel/src/code.erl6
-rw-r--r--lib/kernel/src/code_server.erl9
-rw-r--r--lib/kernel/src/dist_util.erl3
-rw-r--r--lib/kernel/src/file.erl7
-rw-r--r--lib/kernel/src/file_io_server.erl18
-rw-r--r--lib/kernel/src/group.erl8
-rw-r--r--lib/kernel/src/kernel.app.src1
-rw-r--r--lib/kernel/src/packages.erl158
-rw-r--r--lib/kernel/src/user.erl190
-rw-r--r--lib/kernel/test/Makefile1
-rw-r--r--lib/kernel/test/error_logger_warn_SUITE.erl4
-rw-r--r--lib/kernel/test/file_name_SUITE.erl165
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl5
-rw-r--r--lib/kernel/test/heart_SUITE.erl27
-rw-r--r--lib/kernel/test/ignore_cores.erl158
-rw-r--r--lib/kernel/test/ram_file_SUITE.erl17
-rw-r--r--lib/megaco/src/binary/megaco_binary_name_resolver_prev3a.erl6
-rw-r--r--lib/megaco/src/binary/megaco_binary_name_resolver_prev3b.erl6
-rw-r--r--lib/megaco/src/binary/megaco_binary_name_resolver_prev3c.erl6
-rw-r--r--lib/megaco/src/binary/megaco_binary_name_resolver_v3.erl6
-rw-r--r--lib/megaco/test/megaco_codec_prev3a_test.erl4
-rw-r--r--lib/megaco/test/megaco_codec_prev3b_test.erl4
-rw-r--r--lib/megaco/test/megaco_codec_prev3c_test.erl4
-rw-r--r--lib/megaco/test/megaco_codec_v1_test.erl4
-rw-r--r--lib/megaco/test/megaco_codec_v2_test.erl4
-rw-r--r--lib/megaco/test/megaco_codec_v3_test.erl4
-rw-r--r--lib/mnesia/src/mnesia_locker.erl6
-rw-r--r--lib/observer/test/crashdump_viewer_SUITE.erl66
-rw-r--r--lib/odbc/doc/src/odbc.xml12
-rw-r--r--lib/odbc/test/odbc_data_type_SUITE.erl7
-rw-r--r--lib/orber/doc/src/ch_idl_to_erlang_mapping.xml5
-rw-r--r--lib/orber/src/orber_iiop_net.erl24
-rw-r--r--lib/os_mon/src/os_mon.erl4
-rw-r--r--lib/parsetools/include/yeccpre.hrl6
-rw-r--r--lib/parsetools/src/esyntax.yrl360
-rw-r--r--lib/parsetools/src/leex.erl99
-rw-r--r--lib/parsetools/src/yecc.erl120
-rw-r--r--lib/parsetools/src/yeccscan.erl6
-rw-r--r--lib/parsetools/test/leex_SUITE.erl115
-rw-r--r--lib/parsetools/test/yecc_SUITE.erl154
-rw-r--r--lib/public_key/doc/src/public_key.xml7
-rw-r--r--lib/reltool/doc/src/reltool.xml5
-rw-r--r--lib/reltool/src/reltool_target.erl31
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml5
-rw-r--r--lib/runtime_tools/src/runtime_tools_sup.erl3
-rw-r--r--lib/sasl/src/overload.erl5
-rw-r--r--lib/sasl/src/systools_make.erl40
-rw-r--r--lib/snmp/doc/src/notes.xml64
-rw-r--r--lib/snmp/doc/src/snmpm.xml1
-rw-r--r--lib/snmp/src/agent/snmp_view_based_acm_mib.erl2
-rw-r--r--lib/snmp/src/manager/snmpm.erl622
-rw-r--r--lib/snmp/src/manager/snmpm_conf.erl5
-rw-r--r--lib/snmp/src/manager/snmpm_mpd.erl4
-rw-r--r--lib/snmp/test/snmp_agent_test.erl5
-rw-r--r--lib/snmp/test/snmp_log_test.erl12
-rw-r--r--lib/snmp/test/snmp_manager_test.erl217
-rw-r--r--lib/snmp/test/snmp_manager_user.erl318
-rw-r--r--lib/snmp/test/snmp_manager_user_old.erl126
-rw-r--r--lib/snmp/test/snmp_manager_user_test.erl2
-rw-r--r--lib/snmp/test/snmp_test_lib.erl2
-rw-r--r--lib/snmp/test/snmp_test_manager.erl8
-rw-r--r--lib/snmp/vsn.mk2
-rw-r--r--lib/ssh/doc/src/ssh.xml9
-rw-r--r--lib/ssh/doc/src/ssh_sftpd.xml7
-rw-r--r--lib/ssh/doc/src/using_ssh.xml12
-rw-r--r--lib/ssh/src/ssh.appup.src22
-rw-r--r--lib/ssh/src/ssh.erl4
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl22
-rw-r--r--lib/ssh/src/ssh_connection_manager.erl22
-rw-r--r--lib/ssh/src/ssh_sftpd.erl77
-rw-r--r--lib/ssh/src/ssh_xfer.erl5
-rw-r--r--lib/ssh/src/ssh_xfer.hrl12
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl30
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl36
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl21
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl2
-rw-r--r--lib/ssl/doc/src/ssl.xml4
-rw-r--r--lib/ssl/doc/src/ssl_app.xml14
-rw-r--r--lib/ssl/doc/src/ssl_protocol.xml7
-rw-r--r--lib/ssl/src/ssl.erl14
-rw-r--r--lib/ssl/src/ssl_internal.hrl2
-rw-r--r--lib/ssl/src/ssl_record.erl5
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl4
-rw-r--r--lib/stdlib/doc/src/Makefile11
-rw-r--r--lib/stdlib/doc/src/epp.xml59
-rw-r--r--lib/stdlib/doc/src/erl_pp.xml8
-rw-r--r--lib/stdlib/doc/src/io.xml233
-rw-r--r--lib/stdlib/doc/src/io_lib.xml69
-rw-r--r--lib/stdlib/doc/src/io_protocol.xml476
-rw-r--r--lib/stdlib/doc/src/proplists.xml22
-rw-r--r--lib/stdlib/doc/src/re.xml6
-rw-r--r--lib/stdlib/doc/src/unicode.xml71
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml196
-rw-r--r--lib/stdlib/doc/src/ushell1.gifbin13870 -> 0 bytes
-rw-r--r--lib/stdlib/doc/src/ushell1.ps1196
-rw-r--r--lib/stdlib/doc/src/ushell2.gifbin4384 -> 0 bytes
-rw-r--r--lib/stdlib/doc/src/ushell2.ps404
-rw-r--r--lib/stdlib/doc/src/ushell3.gifbin8239 -> 0 bytes
-rw-r--r--lib/stdlib/doc/src/ushell3.ps662
-rw-r--r--lib/stdlib/doc/src/zip.xml4
-rw-r--r--lib/stdlib/src/Makefile1
-rw-r--r--lib/stdlib/src/c.erl2
-rw-r--r--lib/stdlib/src/dict.erl5
-rw-r--r--lib/stdlib/src/edlin.erl7
-rw-r--r--lib/stdlib/src/epp.erl211
-rw-r--r--lib/stdlib/src/erl_eval.erl45
-rw-r--r--lib/stdlib/src/erl_expand_records.erl7
-rw-r--r--lib/stdlib/src/erl_lint.erl229
-rw-r--r--lib/stdlib/src/erl_parse.yrl192
-rw-r--r--lib/stdlib/src/erl_pp.erl759
-rw-r--r--lib/stdlib/src/erl_scan.erl287
-rw-r--r--lib/stdlib/src/escript.erl29
-rw-r--r--lib/stdlib/src/filename.erl2
-rw-r--r--lib/stdlib/src/gb_sets.erl3
-rw-r--r--lib/stdlib/src/gb_trees.erl3
-rw-r--r--lib/stdlib/src/io.erl194
-rw-r--r--lib/stdlib/src/io_lib.erl136
-rw-r--r--lib/stdlib/src/io_lib_format.erl37
-rw-r--r--lib/stdlib/src/io_lib_fread.erl2
-rw-r--r--lib/stdlib/src/io_lib_pretty.erl226
-rw-r--r--lib/stdlib/src/lib.erl173
-rw-r--r--lib/stdlib/src/otp_internal.erl86
-rw-r--r--lib/stdlib/src/proplists.erl72
-rw-r--r--lib/stdlib/src/qlc_pt.erl10
-rw-r--r--lib/stdlib/src/sets.erl5
-rw-r--r--lib/stdlib/src/shell.erl193
-rw-r--r--lib/stdlib/src/string.erl3
-rw-r--r--lib/stdlib/src/sys.erl95
-rw-r--r--lib/stdlib/test/base64_SUITE.erl9
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl9
-rw-r--r--lib/stdlib/test/digraph_SUITE.erl4
-rw-r--r--lib/stdlib/test/epp_SUITE.erl82
-rw-r--r--lib/stdlib/test/erl_expand_records_SUITE.erl14
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl4
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl111
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl214
-rw-r--r--lib/stdlib/test/escript_SUITE.erl21
-rwxr-xr-xlib/stdlib/test/escript_SUITE_data/unicode114
-rwxr-xr-xlib/stdlib/test/escript_SUITE_data/unicode214
-rwxr-xr-xlib/stdlib/test/escript_SUITE_data/unicode313
-rw-r--r--lib/stdlib/test/io_SUITE.erl50
-rw-r--r--lib/stdlib/test/io_proto_SUITE.erl2
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl15
-rw-r--r--lib/stdlib/test/re_SUITE.erl21
-rw-r--r--lib/stdlib/test/re_testoutput1_replacement_test.erl55
-rw-r--r--lib/stdlib/test/re_testoutput1_split_test.erl81
-rw-r--r--lib/stdlib/test/shell_SUITE.erl209
-rw-r--r--lib/stdlib/test/string_SUITE.erl7
-rw-r--r--lib/syntax_tools/src/epp_dodger.erl4
-rw-r--r--lib/syntax_tools/src/erl_comment_scan.erl12
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl38
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl164
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl5
-rw-r--r--lib/syntax_tools/src/erl_tidy.erl11
-rw-r--r--lib/syntax_tools/src/igor.erl55
-rw-r--r--lib/test_server/doc/src/test_server_ctrl.xml93
-rw-r--r--lib/test_server/doc/src/ts.xml4
-rw-r--r--lib/test_server/src/Makefile3
-rw-r--r--lib/test_server/src/erl2html2.erl29
-rw-r--r--lib/test_server/src/test_server.erl92
-rw-r--r--lib/test_server/src/test_server_ctrl.erl318
-rw-r--r--lib/test_server/src/test_server_sup.erl28
-rw-r--r--lib/test_server/src/ts.erl31
-rw-r--r--lib/test_server/test/test_server_SUITE.erl100
-rw-r--r--lib/test_server/test/test_server_SUITE_data/Makefile.src4
-rw-r--r--lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl10
-rw-r--r--lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl58
-rw-r--r--lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl4
-rw-r--r--lib/test_server/test/test_server_test_lib.erl19
-rw-r--r--lib/tools/src/cover.erl80
-rw-r--r--lib/tools/src/lcnt.erl3
-rw-r--r--lib/tools/test/cover_SUITE.erl104
-rw-r--r--lib/tools/test/xref_SUITE.erl3
-rw-r--r--lib/wx/test/wx_basic_SUITE.erl5
-rw-r--r--lib/xmerl/doc/src/motorcycles_dtd.txt3
-rw-r--r--lib/xmerl/src/xmerl_scan.erl5
-rw-r--r--lib/xmerl/src/xmerl_xsd.erl3
-rw-r--r--lib/xmerl/test/xmerl_SUITE.erl7
-rw-r--r--make/otp.mk.in3
-rw-r--r--system/doc/reference_manual/introduction.xml13
345 files changed, 7185 insertions, 7862 deletions
diff --git a/HOWTO/DTRACE.md b/HOWTO/DTRACE.md
index b719c68c59..8fa2fd9d50 100644
--- a/HOWTO/DTRACE.md
+++ b/HOWTO/DTRACE.md
@@ -69,7 +69,8 @@ following may be executed in a different Pthread:
Example output from `lib/runtime_tools/examples/efile_drv.d` while executing
`file:rename("old-name", "new-name")`:
- efile_drv enter tag={3,84} user tag some-user-tag | RENAME (12) | args: old-name new-name , 0 0 (port #Port<0.59>)
+ efile_drv enter tag={3,84} user tag some-user-tag | RENAME (12) | args: old-name new-name ,\
+ 0 0 (port #Port<0.59>)
async I/O worker tag={3,83} | RENAME (12) | efile_drv-int_entry
async I/O worker tag={3,83} | RENAME (12) | efile_drv-int_return
efile_drv return tag={3,83} user tag | RENAME (12) | errno 2
diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot
index c6ebc852a2..a98b0eda7d 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 c6ebc852a2..a98b0eda7d 100644
--- a/bootstrap/bin/start_clean.boot
+++ b/bootstrap/bin/start_clean.boot
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index e09584fdeb..fd36250580 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 0b93439386..72cce89b9d 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_bsm.beam b/bootstrap/lib/compiler/ebin/beam_bsm.beam
index e0ec059999..e0d595bea0 100644
--- a/bootstrap/lib/compiler/ebin/beam_bsm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bsm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam
index b80b543679..2ecba86d56 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_jump.beam b/bootstrap/lib/compiler/ebin/beam_jump.beam
index 07963ae01e..c296bdd18d 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_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam
index 0c3ce5b710..1aa160b998 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/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam
index ae8f3ee903..d2e93214d1 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_parse.beam b/bootstrap/lib/compiler/ebin/core_parse.beam
index 0993838799..ac2a161ced 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/sys_pre_expand.beam b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
index c08dd86a80..4c8547ea27 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam
index 8782fb01a8..8071b9b616 100644
--- a/bootstrap/lib/compiler/ebin/v3_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam
index 3801b77852..97a9a79260 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/kernel/ebin/application_controller.beam b/bootstrap/lib/kernel/ebin/application_controller.beam
index 7dc72beba6..28512de9f1 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/code.beam b/bootstrap/lib/kernel/ebin/code.beam
index f1fd519f50..04150eee56 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 258a7b9181..cd96c87f99 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_1.beam b/bootstrap/lib/kernel/ebin/disk_log_1.beam
index aa2e21382b..d851460d38 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/dist_util.beam b/bootstrap/lib/kernel/ebin/dist_util.beam
index 98d73eef55..8e07296a49 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/file.beam b/bootstrap/lib/kernel/ebin/file.beam
index 45efb31e93..3d3da9c344 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 9ab1228354..b5380a69cf 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/group.beam b/bootstrap/lib/kernel/ebin/group.beam
index bc2ef712aa..2a7e46faf5 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/heart.beam b/bootstrap/lib/kernel/ebin/heart.beam
index 80f0a60c9f..7e81d1610a 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/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
index f8d3e5847a..5b41832dec 100644
--- a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
+++ b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index b2eccbb475..88a97e0ec2 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/inet_dns.beam b/bootstrap/lib/kernel/ebin/inet_dns.beam
index 4b82d77ccc..07b4356f7b 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_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index ee4f541641..1b92542df2 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/kernel.app b/bootstrap/lib/kernel/ebin/kernel.app
index 48f6250828..ca2dc4f7c5 100644
--- a/bootstrap/lib/kernel/ebin/kernel.app
+++ b/bootstrap/lib/kernel/ebin/kernel.app
@@ -28,7 +28,6 @@
application_starter,
auth,
code,
- packages,
code_server,
dist_util,
erl_boot_server,
diff --git a/bootstrap/lib/kernel/ebin/packages.beam b/bootstrap/lib/kernel/ebin/packages.beam
deleted file mode 100644
index 86fb5b6094..0000000000
--- a/bootstrap/lib/kernel/ebin/packages.beam
+++ /dev/null
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user.beam b/bootstrap/lib/kernel/ebin/user.beam
index d678631703..7b761283a0 100644
--- a/bootstrap/lib/kernel/ebin/user.beam
+++ b/bootstrap/lib/kernel/ebin/user.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/base64.beam b/bootstrap/lib/stdlib/ebin/base64.beam
index 1e9589e945..2ca9a4d0b8 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 250be4dcb1..c7ebc3b440 100644
--- a/bootstrap/lib/stdlib/ebin/beam_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/c.beam b/bootstrap/lib/stdlib/ebin/c.beam
index d627009e03..d919fa0a2d 100644
--- a/bootstrap/lib/stdlib/ebin/c.beam
+++ b/bootstrap/lib/stdlib/ebin/c.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam
index 882228c5d8..06ace1f82d 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 f504c8e9d4..4d383902cd 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/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index e48ebd1d89..a3a86afce9 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_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index d097eaf1f1..1445449c6e 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 093bd0f501..764f624cab 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_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index 9dc80f67b9..3b330266f3 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 d7a5103030..144d485b7f 100644
--- a/bootstrap/lib/stdlib/ebin/erl_parse.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_parse.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam
index 32e33ad130..33b1962d20 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 3abab91ce1..7614fe72d8 100644
--- a/bootstrap/lib/stdlib/ebin/erl_scan.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_tar.beam b/bootstrap/lib/stdlib/ebin/erl_tar.beam
index 90ed044a66..89ee92fddb 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/escript.beam b/bootstrap/lib/stdlib/ebin/escript.beam
index 2a29ae551f..f8f3145066 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/eval_bits.beam b/bootstrap/lib/stdlib/ebin/eval_bits.beam
index dc2ea0f521..379fc3655f 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 e118a6ec85..180054c091 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 82dfeb7ca8..65f45632ac 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 f8a42129c1..de676f2bed 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/io.beam b/bootstrap/lib/stdlib/ebin/io.beam
index cade9d5ac6..ddfcca41e8 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 151fcd9d99..9420ea0f53 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 226f8216be..1a7c3393f8 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_pretty.beam b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
index 16fad6af64..b14eb23e7c 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lib.beam b/bootstrap/lib/stdlib/ebin/lib.beam
index 3865cfb227..668ea7eb29 100644
--- a/bootstrap/lib/stdlib/ebin/lib.beam
+++ b/bootstrap/lib/stdlib/ebin/lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index 270d35ef33..cff55cb641 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/proc_lib.beam b/bootstrap/lib/stdlib/ebin/proc_lib.beam
index 25843dfe45..e22b3ad758 100644
--- a/bootstrap/lib/stdlib/ebin/proc_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/proc_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam
index eef4cef042..302dda040f 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 e76d49052d..458684586b 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/re.beam b/bootstrap/lib/stdlib/ebin/re.beam
index f0508c73b3..8001c49672 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/shell.beam b/bootstrap/lib/stdlib/ebin/shell.beam
index 8705c85853..5614d31ac8 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/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam
index 0e16688bc4..aae89985c8 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/unicode.beam b/bootstrap/lib/stdlib/ebin/unicode.beam
index 4e91cf2466..572cb2b6fa 100644
--- a/bootstrap/lib/stdlib/ebin/unicode.beam
+++ b/bootstrap/lib/stdlib/ebin/unicode.beam
Binary files differ
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 2faa46d760..1d67be2e52 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -3706,10 +3706,11 @@ os_prompt% </pre>
the initial function call with which the process was
spawned.</p>
</item>
- <tag><c>{links, <anno>Pids</anno>}</c></tag>
+ <tag><c>{links, <anno>PidsAndPorts</anno>}</c></tag>
<item>
- <p><c><anno>Pids</anno></c> is a list of pids, with processes to
- which the process has a link.</p>
+ <p><c><anno>PidsAndPorts</anno></c> is a list of pids and
+ port identifiers, with processes or ports to which the process
+ has a link.</p>
</item>
<tag><c>{last_calls, false|Calls}</c></tag>
<item>
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 1799f15504..59a91cd40c 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -31,219 +31,116 @@
#
# Important: Use "ubif" for guard BIFs and operators; use "bif" for ordinary BIFs.
#
-# Add new BIFs to the end of the file. Do not bother adding a "packaged BIF name"
-# (such as 'erl.lang.number'); if/when packages will be supported we will add
-# all those names.
+# Add new BIFs to the end of the file.
#
# Note: Guards BIFs require special support in the compiler (to be able to actually
# call them from within a guard).
#
ubif erlang:abs/1
-ubif 'erl.lang.number':abs/1 ebif_abs_1
bif erlang:adler32/1
-bif 'erl.util.crypt.adler32':sum/1 ebif_adler32_1
bif erlang:adler32/2
-bif 'erl.util.crypt.adler32':sum/2 ebif_adler32_2
bif erlang:adler32_combine/3
-bif 'erl.util.crypt.adler32':combine/3 ebif_adler32_combine_3
bif erlang:apply/3
-bif 'erl.lang':apply/3 ebif_apply_3
bif erlang:atom_to_list/1
-bif 'erl.lang.atom':to_string/1 ebif_atom_to_string_1 atom_to_list_1
bif erlang:binary_to_list/1
-bif 'erl.lang.binary':to_list/1 ebif_binary_to_list_1
bif erlang:binary_to_list/3
-bif 'erl.lang.binary':to_list/3 ebif_binary_to_list_3
bif erlang:binary_to_term/1
-bif 'erl.lang.binary':to_term/1 ebif_binary_to_term_1
bif erlang:check_process_code/2
-bif 'erl.system.code':check_process/2 ebif_check_process_code_2
bif erlang:crc32/1
-bif 'erl.util.crypt.crc32':sum/1 ebif_crc32_1
bif erlang:crc32/2
-bif 'erl.util.crypt.crc32':sum/2 ebif_crc32_2
bif erlang:crc32_combine/3
-bif 'erl.util.crypt.crc32':combine/3 ebif_crc32_combine_3
bif erlang:date/0
-bif 'erl.util.date':today/0 ebif_date_0
bif erlang:delete_module/1
-bif 'erl.system.code':delete/1 ebif_delete_module_1
bif erlang:display/1
-bif 'erl.system.debug':display/1 ebif_display_1
bif erlang:display_string/1
-bif 'erl.system.debug':display_string/1 ebif_display_string_1
bif erlang:display_nl/0
-bif 'erl.system.debug':display_nl/0 ebif_display_nl_0
ubif erlang:element/2
-ubif 'erl.lang.tuple':element/2 ebif_element_2
bif erlang:erase/0
-bif 'erl.lang.proc.pdict':erase/0 ebif_erase_0
bif erlang:erase/1
-bif 'erl.lang.proc.pdict':erase/1 ebif_erase_1
bif erlang:exit/1
-bif 'erl.lang':exit/1 ebif_exit_1
bif erlang:exit/2
-bif 'erl.lang.proc':signal/2 ebif_signal_2 exit_2
bif erlang:external_size/1
-bif 'erl.lang.term':external_size/1 ebif_external_size_1
bif erlang:external_size/2
-bif 'erl.lang.term':external_size/2 ebif_external_size_2
ubif erlang:float/1
-ubif 'erl.lang.number':to_float/1 ebif_to_float_1 float_1
bif erlang:float_to_list/1
-bif 'erl.lang.float':to_string/1 ebif_float_to_string_1 float_to_list_1
bif erlang:fun_info/2
-bif 'erl.lang.function':info/2 ebif_fun_info_2
bif erlang:garbage_collect/0
-bif 'erl.system':garbage_collect/0 ebif_garbage_collect_0
bif erlang:garbage_collect/1
-bif 'erl.system':garbage_collect/1 ebif_garbage_collect_1
bif erlang:get/0
-bif 'erl.lang.proc.pdict':get/0 ebif_get_0
bif erlang:get/1
-bif 'erl.lang.proc.pdict':get/1 ebif_get_1
bif erlang:get_keys/1
-bif 'erl.lang.proc.pdict':get_keys/1 ebif_get_keys_1
bif erlang:group_leader/0
-bif 'erl.lang.proc':group_leader/0 ebif_group_leader_0
bif erlang:group_leader/2
-bif 'erl.lang.proc':set_group_leader/2 ebif_group_leader_2
bif erlang:halt/0
-bif 'erl.lang.system':halt/0 ebif_halt_0
bif erlang:halt/1
-bif 'erl.lang.system':halt/1 ebif_halt_1
bif erlang:halt/2
-bif 'erl.lang.system':halt/2 ebif_halt_2
bif erlang:phash/2
bif erlang:phash2/1
bif erlang:phash2/2
-bif 'erl.lang.term':hash/1 ebif_phash2_1
-bif 'erl.lang.term':hash/2 ebif_phash2_2
ubif erlang:hd/1
-ubif 'erl.lang.list':hd/1 ebif_hd_1
bif erlang:integer_to_list/1
-bif 'erl.lang.integer':to_string/1 ebif_integer_to_string_1 integer_to_list_1
bif erlang:is_alive/0
-bif 'erl.lang.node':is_alive/0 ebif_is_alive_0
ubif erlang:length/1
-ubif 'erl.lang.list':length/1 ebif_length_1
bif erlang:link/1
-bif 'erl.lang.proc':link/1 ebif_link_1
bif erlang:list_to_atom/1
-bif 'erl.lang.atom':from_string/1 ebif_string_to_atom_1 list_to_atom_1
bif erlang:list_to_binary/1
-bif 'erl.lang.binary':from_list/1 ebif_list_to_binary_1
bif erlang:list_to_float/1
-bif 'erl.lang.float':from_string/1 ebif_string_to_float_1 list_to_float_1
bif erlang:list_to_integer/1
-bif 'erl.lang.integer':from_string/1 ebif_string_to_integer_1 list_to_integer_1
bif erlang:list_to_pid/1
-bif 'erl.lang.proc':string_to_pid/1 ebif_string_to_pid_1 list_to_pid_1
bif erlang:list_to_tuple/1
-bif 'erl.lang.tuple':from_list/1 ebif_list_to_tuple_1
bif erlang:loaded/0
-bif 'erl.system.code':loaded/0 ebif_loaded_0
bif erlang:localtime/0
-bif 'erl.util.date':local/0 ebif_localtime_0
bif erlang:localtime_to_universaltime/2
-bif 'erl.util.date':local_to_utc/2 ebif_localtime_to_universaltime_2
bif erlang:make_ref/0
-bif 'erl.lang.ref':new/0 ebif_make_ref_0
bif erlang:md5/1
-bif 'erl.util.crypt.md5':digest/1 ebif_md5_1
bif erlang:md5_init/0
-bif 'erl.util.crypt.md5':init/0 ebif_md5_init_0
bif erlang:md5_update/2
-bif 'erl.util.crypt.md5':update/2 ebif_md5_update_2
bif erlang:md5_final/1
-bif 'erl.util.crypt.md5':final/1 ebif_md5_final_1
bif erlang:module_loaded/1
-bif 'erl.system.code':is_loaded/1 ebif_is_loaded_1 module_loaded_1
bif erlang:function_exported/3
-bif 'erl.system.code':is_loaded/3 ebif_is_loaded_3 function_exported_3
bif erlang:monitor_node/2
-bif 'erl.lang.node':monitor/2 ebif_monitor_node_2
bif erlang:monitor_node/3
-bif 'erl.lang.node':monitor/3 ebif_monitor_node_3
ubif erlang:node/1
-ubif 'erl.lang.node':node/1 ebif_node_1
ubif erlang:node/0
-ubif 'erl.lang.node':node/0 ebif_node_0
bif erlang:nodes/1
-bif 'erl.lang.node':nodes/1 ebif_nodes_1
bif erlang:now/0
-bif 'erl.system':now/0 ebif_now_0
bif erlang:open_port/2
-bif 'erl.lang.port':open/2 ebif_open_port_2 open_port_2
bif erlang:pid_to_list/1
-bif 'erl.lang.proc':pid_to_string/1 ebif_pid_to_string_1 pid_to_list_1
bif erlang:ports/0
-bif 'erl.lang.node':ports/0 ebif_ports_0
bif erlang:pre_loaded/0
-bif 'erl.system.code':preloaded/0 ebif_pre_loaded_0
bif erlang:process_flag/2
-bif 'erl.lang.proc':set_flag/2 ebif_process_flag_2
bif erlang:process_flag/3
-bif 'erl.lang.proc':set_flag/3 ebif_process_flag_3
bif erlang:process_info/1
-bif 'erl.lang.proc':info/1 ebif_process_info_1
bif erlang:process_info/2
-bif 'erl.lang.proc':info/2 ebif_process_info_2
bif erlang:processes/0
-bif 'erl.lang.node':processes/0 ebif_processes_0
bif erlang:purge_module/1
-bif 'erl.system.code':purge/1 ebif_purge_module_1
bif erlang:put/2
-bif 'erl.lang.proc.pdict':put/2 ebif_put_2
bif erlang:register/2
-bif 'erl.lang.node':register/2 ebif_register_2
bif erlang:registered/0
-bif 'erl.lang.node':registered/0 ebif_registered_0
ubif erlang:round/1
-ubif 'erl.lang.number':round/1 ebif_round_1
ubif erlang:self/0
-ubif 'erl.lang.proc':self/0 ebif_self_0
bif erlang:setelement/3
-bif 'erl.lang.tuple':setelement/3 ebif_setelement_3
ubif erlang:size/1
-ubif 'erl.lang.term':size/1 ebif_size_1
bif erlang:spawn/3
-bif 'erl.lang.proc':spawn/3 ebif_spawn_3
bif erlang:spawn_link/3
-bif 'erl.lang.proc':spawn_link/3 ebif_spawn_link_3
bif erlang:split_binary/2
-bif 'erl.lang.binary':split/2 ebif_split_binary_2
bif erlang:statistics/1
-bif 'erl.system':statistics/1 ebif_statistics_1
bif erlang:term_to_binary/1
-bif 'erl.lang.binary':from_term/1 ebif_term_to_binary_1
bif erlang:term_to_binary/2
-bif 'erl.lang.binary':from_term/2 ebif_term_to_binary_2
bif erlang:throw/1
-bif 'erl.lang':throw/1 ebif_throw_1
bif erlang:time/0
-bif 'erl.util.date':time_of_day/0 ebif_time_0
ubif erlang:tl/1
-ubif 'erl.lang.list':tl/1 ebif_tl_1
ubif erlang:trunc/1
-ubif 'erl.lang.number':trunc/1 ebif_trunc_1
bif erlang:tuple_to_list/1
-bif 'erl.lang.tuple':to_list/1 ebif_tuple_to_list_1
bif erlang:universaltime/0
-bif 'erl.util.date':utc/0 ebif_universaltime_0
bif erlang:universaltime_to_localtime/1
-bif 'erl.util.date':utc_to_local/1 ebif_universaltime_to_localtime_1
bif erlang:unlink/1
-bif 'erl.lang.proc':unlink/1 ebif_unlink_1
bif erlang:unregister/1
-bif 'erl.lang.node':unregister/1 ebif_unregister_1
bif erlang:whereis/1
-bif 'erl.lang.node':whereis/1 ebif_whereis_1
bif erlang:spawn_opt/1
-bif 'erl.lang.proc':spawn_opt/1 ebif_spawn_opt_1
bif erlang:setnode/2
bif erlang:setnode/3
bif erlang:dist_exit/3
@@ -261,190 +158,106 @@ bif erts_internal:port_get_data/1
# Tracing & debugging.
bif erlang:trace_pattern/2
-bif 'erl.system.debug':trace_pattern/2 ebif_trace_pattern_2
bif erlang:trace_pattern/3
-bif 'erl.system.debug':trace_pattern/3 ebif_trace_pattern_3
bif erlang:trace/3
-bif 'erl.system.debug':trace/3 ebif_trace_3
bif erlang:trace_info/2
-bif 'erl.system.debug':trace_info/2 ebif_trace_info_2
bif erlang:trace_delivered/1
-bif 'erl.system.debug':trace_delivered/1 ebif_trace_delivered_1
bif erlang:seq_trace/2
-bif 'erl.system.debug':seq_trace/2 ebif_seq_trace_2
bif erlang:seq_trace_info/1
-bif 'erl.system.debug':seq_trace_info/1 ebif_seq_trace_info_1
bif erlang:seq_trace_print/1
-bif 'erl.system.debug':seq_trace_print/1 ebif_seq_trace_print_1
bif erlang:seq_trace_print/2
-bif 'erl.system.debug':seq_trace_print/2 ebif_seq_trace_print_2
bif erlang:suspend_process/2
-bif 'erl.system.debug':suspend_process/2 ebif_suspend_process_2
bif erlang:resume_process/1
-bif 'erl.system.debug':resume_process/1 ebif_resume_process_1
bif erlang:process_display/2
-bif 'erl.system.debug':process_display/2 ebif_process_display_2
bif erlang:bump_reductions/1
-bif 'erl.lang.proc':bump_reductions/1 ebif_bump_reductions_1
bif math:cos/1
-bif 'erl.lang.math':cos/1 ebif_math_cos_1
bif math:cosh/1
-bif 'erl.lang.math':cosh/1 ebif_math_cosh_1
bif math:sin/1
-bif 'erl.lang.math':sin/1 ebif_math_sin_1
bif math:sinh/1
-bif 'erl.lang.math':sinh/1 ebif_math_sinh_1
bif math:tan/1
-bif 'erl.lang.math':tan/1 ebif_math_tan_1
bif math:tanh/1
-bif 'erl.lang.math':tanh/1 ebif_math_tanh_1
bif math:acos/1
-bif 'erl.lang.math':acos/1 ebif_math_acos_1
bif math:acosh/1
-bif 'erl.lang.math':acosh/1 ebif_math_acosh_1
bif math:asin/1
-bif 'erl.lang.math':asin/1 ebif_math_asin_1
bif math:asinh/1
-bif 'erl.lang.math':asinh/1 ebif_math_asinh_1
bif math:atan/1
-bif 'erl.lang.math':atan/1 ebif_math_atan_1
bif math:atanh/1
-bif 'erl.lang.math':atanh/1 ebif_math_atanh_1
bif math:erf/1
-bif 'erl.lang.math':erf/1 ebif_math_erf_1
bif math:erfc/1
-bif 'erl.lang.math':erfc/1 ebif_math_erfc_1
bif math:exp/1
-bif 'erl.lang.math':exp/1 ebif_math_exp_1
bif math:log/1
-bif 'erl.lang.math':log/1 ebif_math_log_1
bif math:log10/1
-bif 'erl.lang.math':log10/1 ebif_math_log10_1
bif math:sqrt/1
-bif 'erl.lang.math':sqrt/1 ebif_math_sqrt_1
bif math:atan2/2
-bif 'erl.lang.math':atan2/2 ebif_math_atan2_2
bif math:pow/2
-bif 'erl.lang.math':pow/2 ebif_math_pow_2
bif erlang:start_timer/3
-bif 'erl.lang.timer':start/3 ebif_start_timer_3
bif erlang:send_after/3
-bif 'erl.lang.timer':send_after/3 ebif_send_after_3
bif erlang:cancel_timer/1
-bif 'erl.lang.timer':cancel/1 ebif_cancel_timer_1
bif erlang:read_timer/1
-bif 'erl.lang.timer':read/1 ebif_read_timer_1
bif erlang:make_tuple/2
-bif 'erl.lang.tuple':make/2 ebif_make_tuple_2
bif erlang:append_element/2
-bif 'erl.lang.tuple':append_element/2 ebif_append_element_2
bif erlang:make_tuple/3
bif erlang:system_flag/2
-bif 'erl.system':set_flag/2 ebif_system_flag_2
bif erlang:system_info/1
-bif 'erl.system':info/1 ebif_system_info_1
# New in R9C
bif erlang:system_monitor/0
-bif 'erl.system':monitor/0 ebif_system_monitor_0
bif erlang:system_monitor/1
-bif 'erl.system':monitor/1 ebif_system_monitor_1
bif erlang:system_monitor/2
-bif 'erl.system':monitor/2 ebif_system_monitor_2
# Added 2006-11-07
bif erlang:system_profile/2
-bif 'erl.system':profile/2 ebif_system_profile_2
# End Added 2006-11-07
# Added 2007-01-17
bif erlang:system_profile/0
-bif 'erl.system':profile/0 ebif_system_profile_0
# End Added 2007-01-17
bif erlang:ref_to_list/1
-bif 'erl.lang.ref':to_string/1 ebif_ref_to_string_1 ref_to_list_1
bif erlang:port_to_list/1
-bif 'erl.lang.port':to_string/1 ebif_port_to_string_1 port_to_list_1
bif erlang:fun_to_list/1
-bif 'erl.lang.function':to_string/1 ebif_fun_to_string_1 fun_to_list_1
bif erlang:monitor/2
-bif 'erl.lang.proc':monitor/2 ebif_monitor_2
bif erlang:demonitor/1
-bif 'erl.lang.proc':demonitor/1 ebif_demonitor_1
bif erlang:demonitor/2
-bif 'erl.lang.proc':demonitor/2 ebif_demonitor_2
bif erlang:is_process_alive/1
-bif 'erl.lang.proc':is_alive/1 ebif_proc_is_alive_1 is_process_alive_1
bif erlang:error/1 error_1
-bif 'erl.lang':error/1 ebif_error_1 error_1
bif erlang:error/2 error_2
-bif 'erl.lang':error/2 ebif_error_2 error_2
bif erlang:raise/3 raise_3
-bif 'erl.lang':raise/3 ebif_raise_3 raise_3
bif erlang:get_stacktrace/0
-bif 'erl.lang.proc':get_stacktrace/0 ebif_get_stacktrace_0
bif erlang:is_builtin/3
-bif 'erl.system.code':is_builtin/3 ebif_is_builtin_3
ubif erlang:'and'/2
-ubif 'erl.lang.bool':'and'/2 ebif_and_2
ubif erlang:'or'/2
-ubif 'erl.lang.bool':'or'/2 ebif_or_2
ubif erlang:'xor'/2
-ubif 'erl.lang.bool':'xor'/2 ebif_xor_2
ubif erlang:'not'/1
-ubif 'erl.lang.bool':'not'/1 ebif_not_1
ubif erlang:'>'/2 sgt_2
-ubif 'erl.lang.term':greater/2 ebif_gt_2 sgt_2
ubif erlang:'>='/2 sge_2
-ubif 'erl.lang.term':greater_or_equal/2 ebif_ge_2 sge_2
ubif erlang:'<'/2 slt_2
-ubif 'erl.lang.term':less/2 ebif_lt_2 slt_2
ubif erlang:'=<'/2 sle_2
-ubif 'erl.lang.term':less_or_equal/2 ebif_le_2 sle_2
ubif erlang:'=:='/2 seq_2
-ubif 'erl.lang.term':equal/2 ebif_eq_2 seq_2
ubif erlang:'=='/2 seqeq_2
-ubif 'erl.lang.term':arith_equal/2 ebif_areq_2 seqeq_2
ubif erlang:'=/='/2 sneq_2
-ubif 'erl.lang.term':not_equal/2 ebif_neq_2 sneq_2
ubif erlang:'/='/2 sneqeq_2
-ubif 'erl.lang.term':not_arith_equal/2 ebif_nareq_2 sneqeq_2
ubif erlang:'+'/2 splus_2
-ubif 'erl.lang.number':plus/2 ebif_plus_2 splus_2
ubif erlang:'-'/2 sminus_2
-ubif 'erl.lang.number':minus/2 ebif_minus_2 sminus_2
ubif erlang:'*'/2 stimes_2
-ubif 'erl.lang.number':multiply/2 ebif_multiply_2 stimes_2
ubif erlang:'/'/2 div_2
-ubif 'erl.lang.number':divide/2 ebif_divide_2 div_2
ubif erlang:'div'/2 intdiv_2
-ubif 'erl.lang.integer':'div'/2 ebif_intdiv_2
ubif erlang:'rem'/2
-ubif 'erl.lang.integer':'rem'/2 ebif_rem_2
ubif erlang:'bor'/2
-ubif 'erl.lang.integer':'bor'/2 ebif_bor_2
ubif erlang:'band'/2
-ubif 'erl.lang.integer':'band'/2 ebif_band_2
ubif erlang:'bxor'/2
-ubif 'erl.lang.integer':'bxor'/2 ebif_bxor_2
ubif erlang:'bsl'/2
-ubif 'erl.lang.integer':'bsl'/2 ebif_bsl_2
ubif erlang:'bsr'/2
-ubif 'erl.lang.integer':'bsr'/2 ebif_bsr_2
ubif erlang:'bnot'/1
-ubif 'erl.lang.integer':'bnot'/1 ebif_bnot_1
ubif erlang:'-'/1 sminus_1
-ubif 'erl.lang.number':minus/1 ebif_minus_1 sminus_1
ubif erlang:'+'/1 splus_1
-ubif 'erl.lang.number':plus/1 ebif_plus_1 splus_1
# New operators in R8. These were the only operators missing.
# erlang:send/2, erlang:append/2 and erlang:subtract/2 are now also
@@ -452,45 +265,27 @@ ubif 'erl.lang.number':plus/1 ebif_plus_1 splus_1
# internal references have been updated to the new ebif_... entries.
bif erlang:'!'/2 ebif_bang_2
-bif 'erl.lang.proc':send/2 ebif_send_2 send_2
bif erlang:send/2
-bif 'erl.lang':send/3 ebif_send_3 send_3
bif erlang:send/3
bif erlang:'++'/2 ebif_plusplus_2
-bif 'erl.lang.list':append/2 ebif_append_2 ebif_plusplus_2
bif erlang:append/2
bif erlang:'--'/2 ebif_minusminus_2
-bif 'erl.lang.list':subtract/2 ebif_list_subtract_2 ebif_minusminus_2
bif erlang:subtract/2
ubif erlang:is_atom/1
-ubif 'erl.lang.term':is_atom/1 ebif_is_atom_1
ubif erlang:is_list/1
-ubif 'erl.lang.term':is_list/1 ebif_is_list_1
ubif erlang:is_tuple/1
-ubif 'erl.lang.term':is_tuple/1 ebif_is_tuple_1
ubif erlang:is_float/1
-ubif 'erl.lang.term':is_float/1 ebif_is_float_1
ubif erlang:is_integer/1
-ubif 'erl.lang.term':is_integer/1 ebif_is_integer_1
ubif erlang:is_number/1
-ubif 'erl.lang.term':is_number/1 ebif_is_number_1
ubif erlang:is_pid/1
-ubif 'erl.lang.term':is_pid/1 ebif_is_pid_1
ubif erlang:is_port/1
-ubif 'erl.lang.term':is_port/1 ebif_is_port_1
ubif erlang:is_reference/1
-ubif 'erl.lang.term':is_reference/1 ebif_is_reference_1
ubif erlang:is_binary/1
-ubif 'erl.lang.term':is_binary/1 ebif_is_binary_1
ubif erlang:is_function/1
-ubif 'erl.lang.term':is_function/1 ebif_is_function_1
ubif erlang:is_function/2
-ubif 'erl.lang.term':is_function/2 ebif_is_function_2
ubif erlang:is_record/2
-ubif 'erl.lang.term':is_record/2 ebif_is_record_2
ubif erlang:is_record/3
-ubif 'erl.lang.term':is_record/3 ebif_is_record_3
bif erlang:match_spec_test/3
@@ -499,96 +294,53 @@ bif erlang:match_spec_test/3
#
bif ets:all/0
-bif 'erl.lang.ets':all/0 ebif_ets_all_0
bif ets:new/2
-bif 'erl.lang.ets':new/2 ebif_ets_new_2
bif ets:delete/1
-bif 'erl.lang.ets':delete/1 ebif_ets_delete_1
bif ets:delete/2
-bif 'erl.lang.ets':delete/2 ebif_ets_delete_2
bif ets:delete_all_objects/1
-bif 'erl.lang.ets':delete_all_objects/1 ebif_ets_delete_all_objects_1
bif ets:delete_object/2
-bif 'erl.lang.ets':delete_object/2 ebif_ets_delete_object_2
bif ets:first/1
-bif 'erl.lang.ets':first/1 ebif_ets_first_1
bif ets:is_compiled_ms/1
-bif 'erl.lang.ets':is_compiled_ms/1 ebif_ets_is_compiled_ms_1
bif ets:lookup/2
-bif 'erl.lang.ets':lookup/2 ebif_ets_lookup_2
bif ets:lookup_element/3
-bif 'erl.lang.ets':lookup_element/3 ebif_ets_lookup_element_3
bif ets:info/1
-bif 'erl.lang.ets':info/1 ebif_ets_info_1
bif ets:info/2
-bif 'erl.lang.ets':info/2 ebif_ets_info_2
bif ets:last/1
-bif 'erl.lang.ets':last/1 ebif_ets_last_1
bif ets:match/1
-bif 'erl.lang.ets':match/1 ebif_ets_match_1
bif ets:match/2
-bif 'erl.lang.ets':match/2 ebif_ets_match_2
bif ets:match/3
-bif 'erl.lang.ets':match/3 ebif_ets_match_3
bif ets:match_object/1
-bif 'erl.lang.ets':match_object/1 ebif_ets_match_object_1
bif ets:match_object/2
-bif 'erl.lang.ets':match_object/2 ebif_ets_match_object_2
bif ets:match_object/3
-bif 'erl.lang.ets':match_object/3 ebif_ets_match_object_3
bif ets:member/2
-bif 'erl.lang.ets':is_key/2 ebif_ets_member_2
bif ets:next/2
-bif 'erl.lang.ets':next/2 ebif_ets_next_2
bif ets:prev/2
-bif 'erl.lang.ets':prev/2 ebif_ets_prev_2
bif ets:insert/2
-bif 'erl.lang.ets':insert/2 ebif_ets_insert_2
bif ets:insert_new/2
-bif 'erl.lang.ets':insert_new/2 ebif_ets_insert_new_2
bif ets:rename/2
-bif 'erl.lang.ets':rename/2 ebif_ets_rename_2
bif ets:safe_fixtable/2
-bif 'erl.lang.ets':fixtable/2 ebif_ets_safe_fixtable_2
bif ets:slot/2
-bif 'erl.lang.ets':slot/2 ebif_ets_slot_2
bif ets:update_counter/3
-bif 'erl.lang.ets':update_counter/3 ebif_ets_update_counter_3
bif ets:select/1
-bif 'erl.lang.ets':select/1 ebif_ets_select_1
bif ets:select/2
-bif 'erl.lang.ets':select/2 ebif_ets_select_2
bif ets:select/3
-bif 'erl.lang.ets':select/3 ebif_ets_select_3
bif ets:select_count/2
-bif 'erl.lang.ets':select/2 ebif_ets_select_count_2
bif ets:select_reverse/1
-bif 'erl.lang.ets':select_reverse/1 ebif_ets_select_reverse_1
bif ets:select_reverse/2
-bif 'erl.lang.ets':select_reverse/2 ebif_ets_select_reverse_2
bif ets:select_reverse/3
-bif 'erl.lang.ets':select_reverse/3 ebif_ets_select_reverse_3
bif ets:select_delete/2
-bif 'erl.lang.ets':select_delete/2 ebif_ets_select_delete_2
bif ets:match_spec_compile/1
-bif 'erl.lang.ets':match_spec_compile/1 ebif_ets_match_spec_compile_1
bif ets:match_spec_run_r/3
-bif 'erl.lang.ets':match_spec_run_r/3 ebif_ets_match_spec_run_r_3
#
# Bifs in os module.
#
bif os:putenv/2
-bif 'erl.system.os':setenv/2 ebif_os_setenv_2 os_putenv_2
bif os:getenv/0
-bif 'erl.system.os':getenv/0 ebif_os_getenv_0
bif os:getenv/1
-bif 'erl.system.os':getenv/1 ebif_os_getenv_1
bif os:getpid/0
-bif 'erl.system.os':pid/0 ebif_os_pid_0 os_getpid_0
bif os:timestamp/0
-bif 'erl.system.os':timestamp/0 ebif_os_timestamp_0 os_timestamp_0
#
# Bifs in the erl_ddll module (the module actually does not exist)
@@ -615,13 +367,9 @@ bif re:run/3
#
bif lists:member/2
-bif 'erl.lang.list':is_element/2 ebif_list_is_element_2 lists_member_2
bif lists:reverse/2
-bif 'erl.lang.list':reverse/2 ebif_list_reverse_2 lists_reverse_2
bif lists:keymember/3
-bif 'erl.lang.list.keylist':is_element/3 ebif_keylist_is_element_3 lists_keymember_3
bif lists:keysearch/3
-bif 'erl.lang.list.keylist':search/3 ebif_keylist_search_3 lists_keysearch_3
bif lists:keyfind/3
#
@@ -629,21 +377,13 @@ bif lists:keyfind/3
#
bif erts_debug:disassemble/1
-bif 'erl.system.debug':disassemble/1 ebif_erts_debug_disassemble_1
bif erts_debug:breakpoint/2
-bif 'erl.system.debug':breakpoint/2 ebif_erts_debug_breakpoint_2
bif erts_debug:same/2
-bif 'erl.system.debug':same/2 ebif_erts_debug_same_2
bif erts_debug:flat_size/1
-bif 'erl.system.debug':flat_size/1 ebif_erts_debug_flat_size_1
bif erts_debug:get_internal_state/1
-bif 'erl.system.debug':get_internal_state/1 ebif_erts_debug_get_internal_state_1
bif erts_debug:set_internal_state/2
-bif 'erl.system.debug':set_internal_state/2 ebif_erts_debug_set_internal_state_2
bif erts_debug:display/1
-bif 'erl.system.debug':display/1 ebif_erts_debug_display_1
bif erts_debug:dist_ext_to_term/2
-bif 'erl.system.debug':dist_ext_to_term/2 ebif_erts_debug_dist_ext_to_term_2
bif erts_debug:instructions/0
#
@@ -663,13 +403,9 @@ bif erts_debug:lock_counters/1
#
bif code:get_chunk/2
-bif 'erl.system.code':get_chunk/2 ebif_code_get_chunk_2
bif code:module_md5/1
-bif 'erl.system.code':module_md5/1 ebif_code_module_md5_1
bif code:make_stub_module/3
-bif 'erl.system.code':make_stub_module/3 ebif_code_make_stub_module_3
bif code:is_module_native/1
-bif 'erl.system.code':is_native/1 ebif_code_is_native_1 code_is_module_native_1
#
# New Bifs in R9C.
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index f169a1a34a..64cd93a100 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -67,7 +67,7 @@ dist_msg_dbg(ErtsDistExternal *edep, char *what, byte *buf, int sz)
{
byte *extp = edep->extp;
Eterm msg;
- Sint size = erts_decode_dist_ext_size(edep, 0);
+ Sint size = erts_decode_dist_ext_size(edep);
if (size < 0) {
erts_fprintf(stderr,
"DIST MSG DEBUG: erts_decode_dist_ext_size(%s) failed:\n",
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index bcdb630140..bb08762b26 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -5009,7 +5009,7 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace)
static Eterm seq_trace_fake(Process *p, Eterm arg1)
{
Eterm result = erl_seq_trace_info(p, arg1);
- if (is_tuple(result) && *tuple_val(result) == 2) {
+ if (!is_non_value(result) && is_tuple(result) && *tuple_val(result) == 2) {
return (tuple_val(result))[2];
}
return result;
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 175f04b15b..8cdf954dd2 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -989,6 +989,7 @@ erl_start(int argc, char **argv)
break;
case 'a':
erts_set_user_requested_filename_encoding(ERL_FILENAME_UNKNOWN);
+ break;
default:
erts_fprintf(stderr, "bad filename encoding %s, can be (l,u or a)\n", arg);
erts_usage();
diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h
index f4d73e716a..fb07f3d5bc 100644
--- a/erts/emulator/beam/erl_port.h
+++ b/erts/emulator/beam/erl_port.h
@@ -430,7 +430,7 @@ ERTS_GLB_INLINE void erts_port_release(Port *);
ERTS_GLB_INLINE Port *erts_thr_id2port_sflgs(Eterm id, Uint32 invalid_sflgs);
ERTS_GLB_INLINE void erts_thr_port_release(Port *prt);
#endif
-ERTS_GLB_INLINE Port *erts_thr_drvport2port_raw(ErlDrvPort);
+ERTS_GLB_INLINE Port *erts_thr_drvport2port_raw(ErlDrvPort, int);
ERTS_GLB_INLINE Port *erts_drvport2port_raw(ErlDrvPort drvport);
ERTS_GLB_INLINE Port *erts_drvport2port(ErlDrvPort, erts_aint32_t *);
ERTS_GLB_INLINE Port *erts_drvportid2port(Eterm);
@@ -622,7 +622,7 @@ erts_thr_port_release(Port *prt)
#endif
ERTS_GLB_INLINE Port*
-erts_thr_drvport2port_raw(ErlDrvPort drvport)
+erts_thr_drvport2port_raw(ErlDrvPort drvport, int lock_pdl)
{
#if ERTS_ENABLE_LOCK_CHECK
int emu_thread = erts_lc_is_emu_thr();
@@ -631,6 +631,8 @@ erts_thr_drvport2port_raw(ErlDrvPort drvport)
return NULL;
else {
Port *prt = (Port *) drvport;
+ if (lock_pdl && prt->port_data_lock)
+ driver_pdl_lock(prt->port_data_lock);
#if ERTS_ENABLE_LOCK_CHECK
if (!ERTS_IS_CRASH_DUMPING) {
if (emu_thread) {
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index b661c26036..8ceadcdb8c 100644
--- a/erts/emulator/beam/erl_port_task.c
+++ b/erts/emulator/beam/erl_port_task.c
@@ -120,7 +120,9 @@ struct ErtsPortTaskBusyCallerTable_ {
};
-static void begin_port_cleanup(Port *pp, ErtsPortTask **execq);
+static void begin_port_cleanup(Port *pp,
+ ErtsPortTask **execq,
+ int *processing_busy_q_p);
ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(port_task,
ErtsPortTask,
@@ -1525,7 +1527,7 @@ erts_port_task_free_port(Port *pp)
erts_resume_processes(suspended);
if (!(flags & (ERTS_PTS_FLG_IN_RUNQ|ERTS_PTS_FLG_EXEC)))
- begin_port_cleanup(pp, NULL);
+ begin_port_cleanup(pp, NULL, NULL);
}
/*
@@ -1681,8 +1683,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
begin_handle_tasks:
if (state & ERTS_PORT_SFLG_FREE) {
reds += ERTS_PORT_REDS_FREE;
-
- begin_port_cleanup(pp, &execq);
+ begin_port_cleanup(pp, &execq, &processing_busy_q);
break;
}
@@ -1773,22 +1774,66 @@ release_port(void *vport)
#endif
static void
-begin_port_cleanup(Port *pp, ErtsPortTask **execqp)
+begin_port_cleanup(Port *pp, ErtsPortTask **execqp, int *processing_busy_q_p)
{
int i, max;
- ErtsPortTask *qs[2];
+ ErtsPortTaskBusyCallerTable *tabp;
+ ErtsPortTask *qs[3];
ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(pp));
/*
- * Handle remaining tasks...
+ * Abort remaining tasks...
+ *
+ * We want to process queues in the following order in order
+ * to preserve signal ordering guarantees:
+ * 1. Local busy queue
+ * 2. Local queue
+ * 3. In queue
*/
max = 0;
- if (execqp && *execqp) {
- qs[max++] = *execqp;
+ if (!execqp) {
+ if (pp->sched.taskq.local.busy.first)
+ qs[max++] = pp->sched.taskq.local.busy.first;
+ if (pp->sched.taskq.local.first)
+ qs[max++] = pp->sched.taskq.local.first;
+ }
+ else {
+ if (*processing_busy_q_p) {
+ if (*execqp)
+ qs[max++] = *execqp;
+ if (pp->sched.taskq.local.first)
+ qs[max++] = pp->sched.taskq.local.first;
+ }
+ else {
+ if (pp->sched.taskq.local.busy.first)
+ qs[max++] = pp->sched.taskq.local.busy.first;
+ if (*execqp)
+ qs[max++] = *execqp;
+ }
*execqp = NULL;
+ *processing_busy_q_p = 0;
+ }
+ pp->sched.taskq.local.busy.first = NULL;
+ pp->sched.taskq.local.busy.last = NULL;
+ pp->sched.taskq.local.first = NULL;
+ tabp = pp->sched.taskq.local.busy.table;
+ if (tabp) {
+ int bix;
+ for (bix = 0; bix < ERTS_PORT_TASK_BUSY_CALLER_TABLE_BUCKETS; bix++) {
+ ErtsPortTaskBusyCaller *bcp = tabp->bucket[bix];
+ while (bcp) {
+ ErtsPortTaskBusyCaller *free_bcp = bcp;
+ bcp = bcp->next;
+ if (free_bcp != &tabp->pre_alloc_busy_caller)
+ erts_free(ERTS_ALC_T_BUSY_CALLER, free_bcp);
+ }
+ }
+
+ busy_caller_table_free(tabp);
+ pp->sched.taskq.local.busy.table = NULL;
}
erts_port_task_sched_lock(&pp->sched);
@@ -1875,7 +1920,8 @@ begin_port_cleanup(Port *pp, ErtsPortTask **execqp)
}
erts_smp_atomic32_read_band_nob(&pp->sched.flags,
- ~ERTS_PTS_FLG_HAVE_TASKS);
+ ~(ERTS_PTS_FLG_HAVE_BUSY_TASKS
+ |ERTS_PTS_FLG_HAVE_TASKS));
/*
* Schedule cleanup of port structure...
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index be094862d4..e466f0e299 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -82,9 +82,11 @@ static void pdl_init(void);
#ifdef ERTS_SMP
static void driver_monitor_lock_pdl(Port *p);
static void driver_monitor_unlock_pdl(Port *p);
+#define DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(Port) erts_thr_drvport2port_raw((Port), 1)
#define DRV_MONITOR_LOCK_PDL(Port) driver_monitor_lock_pdl(Port)
#define DRV_MONITOR_UNLOCK_PDL(Port) driver_monitor_unlock_pdl(Port)
#else
+#define DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(Port) erts_thr_drvport2port_raw((Port), 0)
#define DRV_MONITOR_LOCK_PDL(Port) /* nothing */
#define DRV_MONITOR_UNLOCK_PDL(Port) /* nothing */
#endif
@@ -95,7 +97,7 @@ static void driver_monitor_unlock_pdl(Port *p);
static ERTS_INLINE ErlIOQueue*
drvport2ioq(ErlDrvPort drvport)
{
- Port *prt = erts_thr_drvport2port_raw(drvport);
+ Port *prt = erts_thr_drvport2port_raw(drvport, 0);
erts_aint32_t state = erts_atomic32_read_nob(&prt->state);
if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
return NULL;
@@ -2534,6 +2536,8 @@ port_link_failure(Eterm port_id, Eterm linker)
if (IS_TRACED_FL(rp, F_TRACE_PROCS))
trace_proc(NULL, rp, am_getting_unlinked, port_id);
}
+ if (rp_locks)
+ erts_smp_proc_unlock(rp, rp_locks);
}
}
}
@@ -6737,9 +6741,7 @@ int driver_monitor_process(ErlDrvPort drvport,
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
- prt = erts_thr_drvport2port_raw(drvport);
-
- DRV_MONITOR_LOCK_PDL(prt);
+ prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport);
state = erts_atomic32_read_nob(&prt->state);
@@ -6818,9 +6820,7 @@ int driver_demonitor_process(ErlDrvPort drvport,
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
- prt = erts_thr_drvport2port_raw(drvport);
-
- DRV_MONITOR_LOCK_PDL(prt);
+ prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport);
state = erts_atomic32_read_nob(&prt->state);
@@ -6881,9 +6881,7 @@ ErlDrvTermData driver_get_monitored_process(ErlDrvPort drvport,
ErtsSchedulerData *sched = erts_get_scheduler_data();
#endif
- prt = erts_thr_drvport2port_raw(drvport);
-
- DRV_MONITOR_LOCK_PDL(prt);
+ prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport);
state = erts_atomic32_read_nob(&prt->state);
if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) {
diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c
index 5911d76ad9..0e287908b1 100644
--- a/erts/emulator/hipe/hipe_mkliterals.c
+++ b/erts/emulator/hipe/hipe_mkliterals.c
@@ -262,47 +262,6 @@ static const struct literal {
const char *name;
int value;
} literals[] = {
- /* Field offsets in a process struct */
- { "P_HP", offsetof(struct process, htop) },
- { "P_HP_LIMIT", offsetof(struct process, stop) },
- { "P_OFF_HEAP_FIRST", offsetof(struct process, off_heap.first) },
- { "P_MBUF", offsetof(struct process, mbuf) },
- { "P_ID", offsetof(struct process, common.id) },
- { "P_FLAGS", offsetof(struct process, flags) },
- { "P_FVALUE", offsetof(struct process, fvalue) },
- { "P_FREASON", offsetof(struct process, freason) },
- { "P_FTRACE", offsetof(struct process, ftrace) },
- { "P_FCALLS", offsetof(struct process, fcalls) },
- { "P_BEAM_IP", offsetof(struct process, i) },
- { "P_ARITY", offsetof(struct process, arity) },
- { "P_ARG0", offsetof(struct process, def_arg_reg[0]) },
- { "P_ARG1", offsetof(struct process, def_arg_reg[1]) },
- { "P_ARG2", offsetof(struct process, def_arg_reg[2]) },
- { "P_ARG3", offsetof(struct process, def_arg_reg[3]) },
- { "P_ARG4", offsetof(struct process, def_arg_reg[4]) },
- { "P_ARG5", offsetof(struct process, def_arg_reg[5]) },
-#ifdef HIPE
- { "P_NSP", offsetof(struct process, hipe.nsp) },
- { "P_NCALLEE", offsetof(struct process, hipe.ncallee) },
- { "P_CLOSURE", offsetof(struct process, hipe.closure) },
-#if defined(__i386__) || defined(__x86_64__)
- { "P_NSP_LIMIT", offsetof(struct process, hipe.nstack) },
- { "P_CSP", offsetof(struct process, hipe.ncsp) },
-#elif defined(__sparc__) || defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__)
- { "P_NSP_LIMIT", offsetof(struct process, hipe.nstack) },
- { "P_NRA", offsetof(struct process, hipe.nra) },
-#endif
- { "P_NARITY", offsetof(struct process, hipe.narity) },
- { "P_FLOAT_RESULT",
-# ifdef NO_FPE_SIGNALS
- offsetof(struct process, hipe.float_result)
-# endif
- },
-# if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
- { "P_BIF_CALLEE", offsetof(struct process, hipe.bif_callee) },
-# endif
-#endif /* HIPE */
-
/* process flags bits */
{ "F_TIMO", F_TIMO },
@@ -380,8 +339,6 @@ static const struct literal {
{ "MS_SAVEOFFSET_SIZE", field_sizeof(struct erl_bin_match_struct, save_offset)},
/* messages */
- { "P_MSG_FIRST", offsetof(struct process, msg.first) },
- { "P_MSG_SAVE", offsetof(struct process, msg.save) },
{ "MSG_NEXT", offsetof(struct erl_mesg, next) },
/* ARM */
@@ -460,12 +417,14 @@ static const struct atom_literal {
* These depend on configuration options such as heap architecture.
* The compiler accesses these through hipe_bifs:get_rts_param/1.
*/
-static const struct rts_param {
+struct rts_param {
unsigned int nr;
const char *name;
unsigned int is_defined;
int value;
-} rts_params[] = {
+};
+
+static const struct rts_param rts_params[] = {
{ 1, "P_OFF_HEAP_FUNS",
1, offsetof(struct process, off_heap.first)
},
@@ -518,7 +477,53 @@ static const struct rts_param {
{ 19, "MSG_MESSAGE",
1, offsetof(struct erl_mesg, m[0])
},
- /* highest entry ever used == 21 */
+
+ /* Field offsets in a process struct */
+ { 22, "P_HP", 1, offsetof(struct process, htop) },
+ { 23, "P_HP_LIMIT", 1, offsetof(struct process, stop) },
+ { 24, "P_OFF_HEAP_FIRST", 1, offsetof(struct process, off_heap.first) },
+ { 25, "P_MBUF", 1, offsetof(struct process, mbuf) },
+ { 26, "P_ID", 1, offsetof(struct process, common.id) },
+ { 27, "P_FLAGS", 1, offsetof(struct process, flags) },
+ { 28, "P_FVALUE", 1, offsetof(struct process, fvalue) },
+ { 29, "P_FREASON", 1, offsetof(struct process, freason) },
+ { 30, "P_FTRACE", 1, offsetof(struct process, ftrace) },
+ { 31, "P_FCALLS", 1, offsetof(struct process, fcalls) },
+ { 32, "P_BEAM_IP", 1, offsetof(struct process, i) },
+ { 33, "P_ARITY", 1, offsetof(struct process, arity) },
+ { 34, "P_ARG0", 1, offsetof(struct process, def_arg_reg[0]) },
+ { 35, "P_ARG1", 1, offsetof(struct process, def_arg_reg[1]) },
+ { 36, "P_ARG2", 1, offsetof(struct process, def_arg_reg[2]) },
+ { 37, "P_ARG3", 1, offsetof(struct process, def_arg_reg[3]) },
+ { 38, "P_ARG4", 1, offsetof(struct process, def_arg_reg[4]) },
+ { 39, "P_ARG5", 1, offsetof(struct process, def_arg_reg[5]) },
+ { 40, "P_NSP", 1, offsetof(struct process, hipe.nsp) },
+ { 41, "P_NCALLEE", 1, offsetof(struct process, hipe.ncallee) },
+ { 42, "P_CLOSURE", 1, offsetof(struct process, hipe.closure) },
+ { 43, "P_NSP_LIMIT", 1, offsetof(struct process, hipe.nstack) },
+ { 44, "P_CSP",
+#if defined(__i386__) || defined(__x86_64__)
+ 1, offsetof(struct process, hipe.ncsp)
+#endif
+ },
+ { 45, "P_NRA",
+#if defined(__sparc__) || defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__arm__)
+ 1, offsetof(struct process, hipe.nra)
+#endif
+ },
+ { 46, "P_NARITY", 1, offsetof(struct process, hipe.narity) },
+ { 47, "P_FLOAT_RESULT",
+#ifdef NO_FPE_SIGNALS
+ 1, offsetof(struct process, hipe.float_result)
+#endif
+ },
+ { 48, "P_BIF_CALLEE",
+#if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP)
+ 1, offsetof(struct process, hipe.bif_callee)
+#endif
+ },
+ { 49, "P_MSG_FIRST", 1, offsetof(struct process, msg.first) },
+ { 50, "P_MSG_SAVE", 1, offsetof(struct process, msg.save) },
};
#define NR_PARAMS ARRAY_SIZE(rts_params)
diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl
index 461773114e..d5cb4ee1b7 100644
--- a/erts/emulator/test/match_spec_SUITE.erl
+++ b/erts/emulator/test/match_spec_SUITE.erl
@@ -28,7 +28,7 @@
unary_plus/1, unary_minus/1, moving_labels/1]).
-export([fpe/1]).
-export([otp_9422/1]).
-
+-export([faulty_seq_trace/1, do_faulty_seq_trace/0]).
-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]).
@@ -59,6 +59,7 @@ all() ->
ms_trace3, boxed_and_small, destructive_in_test_bif,
guard_exceptions, unary_plus, unary_minus, fpe,
moving_labels,
+ faulty_seq_trace,
otp_9422];
true -> [not_run]
end.
@@ -726,6 +727,19 @@ do_boxed_and_small() ->
{ok, false, _, _} = erlang:match_spec_test({0,3},[{{make_ref(),'_'},[],['$_']}],table),
ok.
+faulty_seq_trace(doc) ->
+ ["Test that faulty seq_trace_call does not crash emulator"];
+faulty_seq_trace(suite) -> [];
+faulty_seq_trace(Config) when is_list(Config) ->
+ ?line {ok, Node} = start_node(match_spec_suite_other),
+ ?line ok = rpc:call(Node,?MODULE,do_faulty_seq_trace,[]),
+ ?line stop_node(Node),
+ ok.
+
+do_faulty_seq_trace() ->
+ {ok,'EXIT',_,_} = erlang:match_spec_test([],[{'_',[],[{message,{set_seq_token,yxa,true}}]}],trace),
+ ok.
+
errchk(Pat) ->
case catch erlang:trace_pattern({?MODULE, f2, 2}, Pat) of
{'EXIT', {badarg, _}} ->
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index bf37e3c2b2..bea586b11c 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 739fdde10a..061db72dd8 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -1756,7 +1756,7 @@ process_flag(_Flag, _Value) ->
{group_leader, GroupLeader :: pid()} |
{heap_size, Size :: non_neg_integer()} |
{initial_call, mfa()} |
- {links, Pids :: [pid() | port()]} |
+ {links, PidsAndPorts :: [pid() | port()]} |
{last_calls, false | (Calls :: [mfa()])} |
{memory, Size :: non_neg_integer()} |
{message_que_len, MessageQueueLen :: non_neg_integer()} |
diff --git a/lib/common_test/doc/src/common_test_app.xml b/lib/common_test/doc/src/common_test_app.xml
index b6d4a633cb..151159ad69 100644
--- a/lib/common_test/doc/src/common_test_app.xml
+++ b/lib/common_test/doc/src/common_test_app.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2012</year>
+ <year>2003</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -170,7 +170,9 @@
<v> UserData = term()</v>
<v> Conns = [atom()]</v>
<v> CSSFile = string()</v>
- <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}]</v>
+ <v> CTHs = [CTHModule |</v>
+ <v>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{CTHModule, CTHInitArgs} |</v>
+ <v>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{CTHModule, CTHInitArgs, CTHPriority}]</v>
<v> CTHModule = atom()</v>
<v> CTHInitArgs = term()</v>
</type>
@@ -297,8 +299,9 @@
<v> UserData = term()</v>
<v> Conns = [atom()]</v>
<v> CSSFile = string()</v>
- <v> CTHs = [CTHModule | {CTHModule, CTHInitArgs} |
- {CTHModule, CTHInitArgs, CTHPriority}]</v>
+ <v> CTHs = [CTHModule |</v>
+ <v> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{CTHModule, CTHInitArgs} |</v>
+ <v> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{CTHModule, CTHInitArgs, CTHPriority}]</v>
<v> CTHModule = atom()</v>
<v> CTHInitArgs = term()</v>
</type>
diff --git a/lib/common_test/doc/src/cover_chapter.xml b/lib/common_test/doc/src/cover_chapter.xml
index b2e64bfff0..4fa92d5583 100644
--- a/lib/common_test/doc/src/cover_chapter.xml
+++ b/lib/common_test/doc/src/cover_chapter.xml
@@ -108,8 +108,8 @@
specifications</seealso>).</p>
</section>
+ <marker id="cover_stop"></marker>
<section>
- <marker id="cover_stop"></marker>
<title>Stopping the cover tool when tests are completed</title>
<p>By default the Cover tool is automatically stopped when the
tests are completed. This causes the original (non cover
@@ -175,6 +175,11 @@
%% Specific modules to exclude in cover.
{excl_mods, Mods}.
+
+ %% Cross cover compilation
+ %% Tag = atom(), an identifier for a test run
+ %% Mod = [atom()], modules to compile for accumulated analysis
+ {cross,[{Tag,Mods}]}.
</pre>
<p>The <c>incl_dirs_r</c> and <c>excl_dirs_r</c> terms tell Common
@@ -190,6 +195,81 @@
specification file for Common Test).</p>
</section>
+ <marker id="cross_cover"/>
+ <section>
+ <title>Cross cover analysis</title>
+ <p>The cross cover mechanism allows cover analysis of modules
+ across multiple tests. It is useful if some code, e.g. a library
+ module, is used by many different tests and the accumulated cover
+ result is desirable.</p>
+
+ <p>This can of course also be achieved in a more customized way by
+ using the <c>export</c> parameter in the cover specification and
+ analysing the result off line, but the cross cover mechanism is a
+ build in solution which also provides the logging.</p>
+
+ <p>The mechanism is easiest explained via an example:</p>
+
+ <p>Let's say that there are two systems, <c>s1</c> and <c>s2</c>,
+ which are tested in separate test runs. System <c>s1</c> contains
+ a library module <c>m1</c> which is tested by the <c>s1</c> test
+ run and is included in <c>s1</c>'s cover specification:</p>
+
+<code type="none">
+s1.cover:
+ {incl_mods,[m1]}.</code>
+
+ <p>When analysing code coverage, the result for <c>m1</c> can be
+ seen in the cover log in the <c>s1</c> test result.</p>
+
+ <p>Now, let's imagine that since <c>m1</c> is a library module, it
+ is also used quite a bit by system <c>s2</c>. The <c>s2</c> test
+ run does not specifically test <c>m1</c>, but it might still be
+ interesting to see which parts of <c>m1</c> is actually covered by
+ the <c>s2</c> tests. To do this, <c>m1</c> could be included also
+ in <c>s2</c>'s cover specification:</p>
+
+<code type="none">
+s2.cover:
+ {incl_mods,[m1]}.</code>
+
+ <p>This would give an entry for <c>m1</c> also in the cover log
+ for the <c>s2</c> test run. The problem is that this would only
+ reflect the coverage by <c>s2</c> tests, not the accumulated
+ result over <c>s1</c> and <c>s2</c>. And this is where the cross
+ cover mechanism comes in handy.</p>
+
+ <p>If instead the cover specification for <c>s2</c> was like
+ this:</p>
+
+<code type="none">
+s2.cover:
+ {cross,[{s1,[m1]}]}.</code>
+
+ <p>then <c>m1</c> would be cover compiled in the <c>s2</c> test
+ run, but not shown in the coverage log. Instead, if
+ <c>ct_cover:cross_cover_analyse/2</c> is called after both
+ <c>s1</c> and <c>s2</c> test runs are completed, the accumulated
+ result for <c>m1</c> would be available in the cross cover log for
+ the <c>s1</c> test run.</p>
+
+ <p>The call to the analyse function must be like this:</p>
+
+<code type="none">
+ct_cover:cross_cover_analyse(Level, [{s1,S1LogDir},{s2,S2LogDir}]).</code>
+
+ <p>where <c>S1LogDir</c> and <c>S2LogDir</c> are the directories
+ named <c>&lt;TestName&gt;.logs</c> for each test respectively.</p>
+
+ <p>Note the tags <c>s1</c> and <c>s2</c> which are used in the
+ cover specification file and in the call to
+ <c>ct_cover:cross_cover_analyse/2</c>. The point of these are only
+ to map the modules specified in the cover specification to the log
+ directory specified in the call to the analyse function. The name
+ of the tag has no meaning beyond this.</p>
+
+ </section>
+
<section>
<title>Logging</title>
<p>To view the result of a code coverage test, follow the
@@ -197,6 +277,11 @@
takes you to the code coverage overview page. If you have
successfully performed a detailed coverage analysis, you
find links to each individual module coverage page here.</p>
+
+ <p>If cross cover analysis has been performed, and there are
+ accumulated coverage results for the current test, then the -
+ "Coverdata collected over all tests" link will take you to these
+ results.</p>
</section>
</chapter>
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index 86237f5fc1..fe871eb516 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2011</year><year>2012</year>
+ <year>2011</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -439,14 +439,14 @@ terminate(State) ->
<table>
<row>
- <cell><em>CTH Name</em></cell>
- <cell><em>Is Built-in</em></cell>
- <cell><em>Description</em></cell>
+ <cell align="left"><em>CTH Name</em></cell>
+ <cell align="left"><em>Is Built-in</em></cell>
+ <cell align="left"><em>Description</em></cell>
</row>
<row>
- <cell>cth_log_redirect</cell>
- <cell>yes</cell>
- <cell>Captures all error_logger and SASL logging events and prints them
+ <cell align="left">cth_log_redirect</cell>
+ <cell align="left">yes</cell>
+ <cell align="left">Captures all error_logger and SASL logging events and prints them
to the current test case log. If an event can not be associated with a
testcase it will be printed in the common test framework log. This will
happen for testcases which are run in parallel and events which occur
@@ -455,14 +455,29 @@ terminate(State) ->
using the normal SASL mechanisms. </cell>
</row>
<row>
- <cell>cth_surefire</cell>
- <cell>no</cell>
- <cell>Captures all test results and outputs them as surefire XML into
- a file. The file which is created is by default called junit_report.xml.
- The name can be by setting the path option for this hook. e.g.
+ <cell align="left">cth_surefire</cell>
+ <cell align="left">no</cell>
+ <cell align="left"><p>Captures all test results and outputs them as surefire
+ XML into a file. The file which is created is by default
+ called junit_report.xml. The file name can be changed by
+ setting the <c>path</c> option for this hook, e.g.</p>
+
<code>-ct_hooks cth_surefire [{path,"/tmp/report.xml"}]</code>
- Surefire XML can forinstance be used by Jenkins to display test
- results.</cell>
+
+ <p>If the <c>url_base</c> option is set, an additional
+ attribute named <c>url</c> will be added to each
+ <c>testsuite</c> and <c>testcase</c> XML element. The value will
+ be constructed from the <c>url_base</c> and a relative path
+ to the test suite or test case log respectively, e.g.</p>
+
+ <code>-ct_hooks cth_surefire [{url_base, "http://myserver.com/"}]</code>
+ <p>will give a url attribute value similar to</p>
+
+ <code>"http://myserver.com/[email protected]_11.19.39/
+x86_64-unknown-linux-gnu.my_test.logs/run.2012-12-12_11.19.39/suite.log.html"</code>
+
+ <p>Surefire XML can for instance be used by Jenkins to display test
+ results.</p></cell>
</row>
</table>
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index 7e33b71de1..8c3b13951d 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -32,6 +32,56 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.6.3.1</title>
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ The following corrections/changes are done in the
+ cth_surefire hook:</p>
+ <p>
+ <list> <item> Earlier there would always be a
+ 'properties' element under the 'testsuites' element. This
+ would exist even if there were no 'property' element
+ inside it. This has been changed so if there are no
+ 'property' elements to display, then there will not be a
+ 'properties' element either. </item> <item> The XML file
+ will now (unless other is specified) be stored in the top
+ log directory. Earlier, the default directory would be
+ the current working directory for the erlang node, which
+ would mostly, but not always, be the top log directory.
+ </item> <item> The 'hostname' attribute in the
+ 'testsuite' element would earlier never have the correct
+ value. This has been corrected. </item> <item> The
+ 'errors' attribute in the 'testsuite' element would
+ earlier display the number of failed testcases. This has
+ been changed and will now always have the value 0, while
+ the 'failures' attribute will show the number of failed
+ testcases. </item> <item> A new attribute 'skipped' is
+ added to the 'testsuite' element. This will display the
+ number of skipped testcases. These would earlier be
+ included in the number of failed test cases. </item>
+ <item> The total number of tests displayed by the 'tests'
+ attribute in the 'testsuite' element would earlier
+ include init/end_per_suite and init/end_per_group. This
+ is no longer the case. The 'tests' attribute will now
+ only count "real" test cases. </item> <item> Earlier,
+ auto skipped test cases would have no value in the 'log'
+ attribute. This is now corrected. </item> <item> A new
+ attributes 'log' is added to the 'testsuite' element.
+ </item> <item> A new option named 'url_base' is added for
+ this hook. If this option is used, a new attribute named
+ 'url' will be added to the 'testcase' and 'testsuite'
+ elements. </item> </list></p>
+ <p>
+ Own Id: OTP-10589</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.6.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml
index b804f134c6..d5f5d89e05 100644
--- a/lib/common_test/doc/src/run_test_chapter.xml
+++ b/lib/common_test/doc/src/run_test_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2012</year>
+ <year>2003</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -752,7 +752,9 @@
PrivDirOption = auto_per_run | auto_per_tc | manual_per_tc
EventHandlers = atom() | [atom()]
InitArgs = [term()]
- CTHModules = [CTHModule | {CTHModule, CTHInitArgs} | {CTHModule, CTHInitArgs, CTHPriority}]
+ CTHModules = [CTHModule |
+ {CTHModule, CTHInitArgs} |
+ {CTHModule, CTHInitArgs, CTHPriority}]
CTHModule = atom()
CTHInitArgs = term()
Dir = string()
diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml
index 248d7de8b6..cc8d913994 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>2012</year>
+ <year>2003</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -982,38 +982,36 @@
<p>Example:</p>
<pre>
+ Some printouts during test case execution:
- Some printouts during test case execution:
+ io:format("1. Standard IO, importance = ~w~n", [?STD_IMPORTANCE]),
+ ct:log("2. Uncategorized, importance = ~w", [?STD_IMPORTANCE]),
+ ct:log(info, "3. Categorized info, importance = ~w", [?STD_IMPORTANCE]]),
+ ct:log(info, ?LOW_IMPORTANCE, "4. Categorized info, importance = ~w", [?LOW_IMPORTANCE]),
+ ct:log(error, "5. Categorized error, importance = ~w", [?HI_IMPORTANCE]),
+ ct:log(error, ?HI_IMPORTANCE, "6. Categorized error, importance = ~w", [?MAX_IMPORTANCE]),
- io:format("1. Standard IO, importance = ~w~n", [?STD_IMPORTANCE]),
- ct:log("2. Uncategorized, importance = ~w", [?STD_IMPORTANCE]),
- ct:log(info, "3. Categorized info, importance = ~w", [?STD_IMPORTANCE]]),
- ct:log(info, ?LOW_IMPORTANCE, "4. Categorized info, importance = ~w", [?LOW_IMPORTANCE]),
- ct:log(error, "5. Categorized error, importance = ~w", [?HI_IMPORTANCE]),
- ct:log(error, ?HI_IMPORTANCE, "6. Categorized error, importance = ~w", [?MAX_IMPORTANCE]),
+ If starting the test without specifying any verbosity levels:
- If starting the test without specifying any verbosity levels:
+ $ ct_run ...
- $ ct_run ...
+ the following gets printed:
- the following gets printed:
-
- 1. Standard IO, importance = 50
- 2. Uncategorized, importance = 50
- 3. Categorized info, importance = 50
- 5. Categorized error, importance = 75
- 6. Categorized error, importance = 99
-
- If starting the test with:
-
- $ ct_run -verbosity 1 and info 75
-
- the following gets printed:
+ 1. Standard IO, importance = 50
+ 2. Uncategorized, importance = 50
+ 3. Categorized info, importance = 50
+ 5. Categorized error, importance = 75
+ 6. Categorized error, importance = 99
+
+ If starting the test with:
+
+ $ ct_run -verbosity 1 and info 75
+
+ the following gets printed:
- 3. Categorized info, importance = 50
- 4. Categorized info, importance = 25
- 6. Categorized error, importance = 99
- </pre>
+ 3. Categorized info, importance = 50
+ 4. Categorized info, importance = 25
+ 6. Categorized error, importance = 99</pre>
<p>How categories can be mapped to CSS tags is documented in the
<seealso marker="run_test_chapter#html_stylesheet">Running Tests</seealso>
diff --git a/lib/common_test/src/ct_cover.erl b/lib/common_test/src/ct_cover.erl
index d39f50ba00..ae671c750a 100644
--- a/lib/common_test/src/ct_cover.erl
+++ b/lib/common_test/src/ct_cover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,7 +24,7 @@
-module(ct_cover).
--export([get_spec/1, add_nodes/1, remove_nodes/1]).
+-export([get_spec/1, add_nodes/1, remove_nodes/1, cross_cover_analyse/2]).
-include("ct_util.hrl").
@@ -100,6 +100,22 @@ remove_nodes(Nodes) ->
%%%-----------------------------------------------------------------
+%%% @spec cross_cover_analyse(Level,Tests) -> ok
+%%% Level = overview | details
+%%% Tests = [{Tag,Dir}]
+%%% Tag = atom()
+%%% Dir = string()
+%%%
+%%% @doc Accumulate cover results over multiple tests.
+%%% See the chapter about <seealso
+%%% marker="cover_chapter#cross_cover">cross cover
+%%% analysis</seealso> in the users's guide.
+%%%
+cross_cover_analyse(Level,Tests) ->
+ test_server_ctrl:cross_cover_analyse(Level,Tests).
+
+
+%%%-----------------------------------------------------------------
%%% @hidden
%% Read cover specification file and return the parsed info.
@@ -249,9 +265,11 @@ get_app_info(App=#cover{app=Name}, [{excl_mods,Name,Mods1}|Terms]) ->
Mods = App#cover.excl_mods,
get_app_info(App#cover{excl_mods=Mods++Mods1},Terms);
-get_app_info(App=#cover{app=Name}, [{cross_apps,Name,AppMods1}|Terms]) ->
- AppMods = App#cover.cross,
- get_app_info(App#cover{cross=AppMods++AppMods1},Terms);
+get_app_info(App=#cover{app=none}, [{cross,Cross}|Terms]) ->
+ get_app_info(App, [{cross,none,Cross}|Terms]);
+get_app_info(App=#cover{app=Name}, [{cross,Name,Cross1}|Terms]) ->
+ Cross = App#cover.cross,
+ get_app_info(App#cover{cross=Cross++Cross1},Terms);
get_app_info(App=#cover{app=none}, [{src_dirs,Dirs}|Terms]) ->
get_app_info(App, [{src_dirs,none,Dirs}|Terms]);
@@ -354,10 +372,10 @@ remove_excludes_and_dups(CoverData=#cover{excl_mods=Excl,incl_mods=Incl}) ->
files2mods(Info=#cover{excl_mods=ExclFs,
incl_mods=InclFs,
- cross=CrossFs}) ->
+ cross=Cross}) ->
Info#cover{excl_mods=files2mods1(ExclFs),
incl_mods=files2mods1(InclFs),
- cross=files2mods1(CrossFs)}.
+ cross=[{Tag,files2mods1(Fs)} || {Tag,Fs} <- Cross]}.
files2mods1([M|Fs]) when is_atom(M) ->
[M|files2mods1(Fs)];
diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl
index 11c8235040..1ccbc86d8f 100644
--- a/lib/common_test/src/ct_netconfc.erl
+++ b/lib/common_test/src/ct_netconfc.erl
@@ -1073,7 +1073,8 @@ handle_msg({get_event_streams=Op,Streams,Timeout}, From, State) ->
SimpleXml = encode_rpc_operation(get,[Filter]),
do_send_rpc(Op, SimpleXml, Timeout, From, State).
-handle_msg({ssh_cm, _CM, {data, _Ch, _Type, Data}}, State) ->
+handle_msg({ssh_cm, CM, {data, Ch, _Type, Data}}, State) ->
+ ssh_connection:adjust_window(CM,Ch,size(Data)),
handle_data(Data, State);
handle_msg({ssh_cm, _CM, _SshCloseMsg}, State) ->
%% _SshCloseMsg can probably be one of
@@ -1805,7 +1806,8 @@ get_tag([]) ->
%%% SSH stuff
ssh_receive_data() ->
receive
- {ssh_cm, _CM, {data, _Ch, _Type, Data}} ->
+ {ssh_cm, CM, {data, Ch, _Type, Data}} ->
+ ssh_connection:adjust_window(CM,Ch,size(Data)),
{ok, Data};
{ssh_cm, _CM, {Closed, _Ch}} = X when Closed == closed; Closed == eof ->
{error,X};
diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl
index 58633b7de6..1fd8c04f8b 100644
--- a/lib/common_test/src/ct_slave.erl
+++ b/lib/common_test/src/ct_slave.erl
@@ -449,15 +449,29 @@ wait_for_node_alive(Node, N) ->
% call init:stop on a remote node
do_stop(ENode) ->
- case test_server:is_cover() of
- true ->
- MainCoverNode = cover:get_main_node(),
- rpc:call(MainCoverNode,cover,flush,[ENode]);
- false ->
- ok
+ {Cover,MainCoverNode} =
+ case test_server:is_cover() of
+ true ->
+ Main = cover:get_main_node(),
+ rpc:call(Main,cover,flush,[ENode]),
+ {true,Main};
+ false ->
+ {false,undefined}
end,
spawn(ENode, init, stop, []),
- wait_for_node_dead(ENode, 5).
+ case wait_for_node_dead(ENode, 5) of
+ {ok,ENode} ->
+ if Cover ->
+ %% To avoid that cover is started again if a node
+ %% with the same name is started later.
+ rpc:call(MainCoverNode,cover,stop,[ENode]);
+ true ->
+ ok
+ end,
+ {ok,ENode};
+ Error ->
+ Error
+ end.
% wait N seconds until node is disconnected
wait_for_node_dead(Node, 0) ->
diff --git a/lib/common_test/src/cth_surefire.erl b/lib/common_test/src/cth_surefire.erl
index 76b0f0b5ea..e6eaad8d48 100644
--- a/lib/common_test/src/cth_surefire.erl
+++ b/lib/common_test/src/cth_surefire.erl
@@ -1,3 +1,22 @@
+%%--------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%--------------------------------------------------------------------
+
%%% @doc Common Test Framework functions handling test specifications.
%%%
%%% <p>This module creates a junit report of the test run if plugged in
@@ -27,18 +46,28 @@
-export([terminate/1]).
-record(state, { filepath, axis, properties, package, hostname,
- curr_suite, curr_suite_ts, curr_group = [], curr_tc,
- curr_log_dir, timer, tc_log,
+ curr_suite, curr_suite_ts, curr_group = [],
+ curr_log_dir, timer, tc_log, url_base,
test_cases = [],
test_suites = [] }).
--record(testcase, { log, group, classname, name, time, failure, timestamp }).
--record(testsuite, { errors, failures, hostname, name, tests,
+-record(testcase, { log, url, group, classname, name, time, result, timestamp }).
+-record(testsuite, { errors, failures, skipped, hostname, name, tests,
time, timestamp, id, package,
- properties, testcases }).
+ properties, testcases, log, url }).
+
+-define(default_report,"junit_report.xml").
+-define(suite_log,"suite.log.html").
+
+%% Number of dirs from log root to testcase log file.
+%% ct_run.<node>.<timestamp>/<test_name>/run.<timestamp>/<tc_log>.html
+-define(log_depth,3).
id(Opts) ->
- filename:absname(proplists:get_value(path, Opts, "junit_report.xml")).
+ case proplists:get_value(path, Opts) of
+ undefined -> ?default_report;
+ Path -> filename:absname(Path)
+ end.
init(Path, Opts) ->
{ok, Host} = inet:gethostname(),
@@ -47,10 +76,24 @@ init(Path, Opts) ->
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,Config,#state{ test_cases = [] } = State) ->
- {Config, init_tc(State#state{ curr_suite = Suite, curr_suite_ts = now() },
+ TcLog = proplists:get_value(tc_logfile,Config),
+ CurrLogDir = filename:dirname(TcLog),
+ Path =
+ case State#state.filepath of
+ ?default_report ->
+ RootDir = get_test_root(TcLog),
+ filename:join(RootDir,?default_report);
+ P ->
+ P
+ end,
+ {Config, init_tc(State#state{ filepath = Path,
+ curr_suite = Suite,
+ curr_suite_ts = now(),
+ curr_log_dir = CurrLogDir},
Config) };
pre_init_per_suite(Suite,Config,State) ->
%% Have to close the previous suite
@@ -59,7 +102,8 @@ pre_init_per_suite(Suite,Config,State) ->
post_init_per_suite(_Suite,Config, Result, State) ->
{Result, end_tc(init_per_suite,Config,Result,State)}.
-pre_end_per_suite(_Suite,Config,State) -> {Config, init_tc(State, Config)}.
+pre_end_per_suite(_Suite,Config,State) ->
+ {Config, init_tc(State, Config)}.
post_end_per_suite(_Suite,Config,Result,State) ->
{Result, end_tc(end_per_suite,Config,Result,State)}.
@@ -71,13 +115,15 @@ pre_init_per_group(Group,Config,State) ->
post_init_per_group(_Group,Config,Result,State) ->
{Result, end_tc(init_per_group,Config,Result,State)}.
-pre_end_per_group(_Group,Config,State) -> {Config, init_tc(State, Config)}.
+pre_end_per_group(_Group,Config,State) ->
+ {Config, init_tc(State, Config)}.
post_end_per_group(_Group,Config,Result,State) ->
NewState = end_tc(end_per_group, Config, Result, State),
{Result, NewState#state{ curr_group = tl(NewState#state.curr_group)}}.
-pre_init_per_testcase(_TC,Config,State) -> {Config, init_tc(State, Config)}.
+pre_init_per_testcase(_TC,Config,State) ->
+ {Config, init_tc(State, Config)}.
post_end_per_testcase(TC,Config,Result,State) ->
{Result, end_tc(TC,Config, Result,State)}.
@@ -88,11 +134,19 @@ on_tc_fail(_TC, Res, State) ->
TCs = State#state.test_cases,
TC = hd(TCs),
NewTC = TC#testcase{
- failure =
+ result =
{fail,lists:flatten(io_lib:format("~p",[Res]))} },
State#state{ test_cases = [NewTC | tl(TCs)]}.
-on_tc_skip(Tc,{Type,_Reason} = Res, State) when Type == tc_auto_skip ->
+on_tc_skip(Tc,{Type,_Reason} = Res, State0) when Type == tc_auto_skip ->
+ TcStr = atom_to_list(Tc),
+ State =
+ case State0#state.test_cases of
+ [#testcase{name=TcStr}|TCs] ->
+ State0#state{test_cases=TCs};
+ _ ->
+ State0
+ end,
do_tc_skip(Res, end_tc(Tc,[],Res,init_tc(State,[])));
on_tc_skip(_Tc, _Res, State = #state{test_cases = []}) ->
State;
@@ -103,7 +157,7 @@ do_tc_skip(Res, State) ->
TCs = State#state.test_cases,
TC = hd(TCs),
NewTC = TC#testcase{
- failure =
+ result =
{skipped,lists:flatten(io_lib:format("~p",[Res]))} },
State#state{ test_cases = [NewTC | tl(TCs)]}.
@@ -117,33 +171,52 @@ end_tc(Func, Config, Res, State) when is_atom(Func) ->
end_tc(atom_to_list(Func), Config, Res, State);
end_tc(Name, _Config, _Res, State = #state{ curr_suite = Suite,
curr_group = Groups,
- timer = TS, tc_log = Log } ) ->
+ curr_log_dir = CurrLogDir,
+ timer = TS,
+ tc_log = Log0,
+ url_base = UrlBase } ) ->
+ Log =
+ case Log0 of
+ "" ->
+ LowerSuiteName = string:to_lower(atom_to_list(Suite)),
+ filename:join(CurrLogDir,LowerSuiteName++"."++Name++".html");
+ _ ->
+ Log0
+ end,
+ Url = make_url(UrlBase,Log),
ClassName = atom_to_list(Suite),
PGroup = string:join([ atom_to_list(Group)||
Group <- lists:reverse(Groups)],"."),
TimeTakes = io_lib:format("~f",[timer:now_diff(now(),TS) / 1000000]),
State#state{ test_cases = [#testcase{ log = Log,
+ url = Url,
timestamp = now_to_string(TS),
classname = ClassName,
group = PGroup,
name = Name,
time = TimeTakes,
- failure = passed }| State#state.test_cases]}.
+ result = passed }|
+ State#state.test_cases],
+ tc_log = ""}. % so old tc_log is not set if next is on_tc_skip
close_suite(#state{ test_cases = [] } = State) ->
State;
-close_suite(#state{ test_cases = TCs } = State) ->
- Total = length(TCs),
- Succ = length(lists:filter(fun(#testcase{ failure = F }) ->
- F == passed
- end,TCs)),
- Fail = Total - Succ,
+close_suite(#state{ test_cases = TCs, url_base = UrlBase } = State) ->
+ {Total,Fail,Skip} = count_tcs(TCs,0,0,0),
TimeTaken = timer:now_diff(now(),State#state.curr_suite_ts) / 1000000,
+ SuiteLog = filename:join(State#state.curr_log_dir,?suite_log),
+ SuiteUrl = make_url(UrlBase,SuiteLog),
Suite = #testsuite{ name = atom_to_list(State#state.curr_suite),
package = State#state.package,
+ hostname = State#state.hostname,
time = io_lib:format("~f",[TimeTaken]),
timestamp = now_to_string(State#state.curr_suite_ts),
- errors = Fail, tests = Total,
- testcases = lists:reverse(TCs) },
+ errors = 0,
+ failures = Fail,
+ skipped = Skip,
+ tests = Total,
+ testcases = lists:reverse(TCs),
+ log = SuiteLog,
+ url = SuiteUrl},
State#state{ test_cases = [],
test_suites = [Suite | State#state.test_suites]}.
@@ -159,14 +232,15 @@ terminate(State) ->
-to_xml(#testcase{ group = Group, classname = CL, log = L, name = N, time = T, timestamp = TS, failure = F}) ->
+to_xml(#testcase{ group = Group, classname = CL, log = L, url = U, name = N, time = T, timestamp = TS, result = R}) ->
["<testcase ",
- [["group=\"",Group,"\""]||Group /= ""]," "
+ [["group=\"",Group,"\" "]||Group /= ""],
"name=\"",N,"\" "
"time=\"",T,"\" "
- "timestamp=\"",TS,"\" "
+ "timestamp=\"",TS,"\" ",
+ [["url=\"",U,"\" "]||U /= undefined],
"log=\"",L,"\">",
- case F of
+ case R of
passed ->
[];
{skipped,Reason} ->
@@ -176,22 +250,29 @@ to_xml(#testcase{ group = Group, classname = CL, log = L, name = N, time = T, ti
["<failure message=\"Test ",N," in ",CL," failed!\" type=\"crash\">",
sanitize(Reason),"</failure>"]
end,"</testcase>"];
-to_xml(#testsuite{ package = P, hostname = H, errors = E, time = Time,
- timestamp = TS, tests = T, name = N, testcases = Cases }) ->
+to_xml(#testsuite{ package = P, hostname = H, errors = E, failures = F,
+ skipped = S, time = Time, timestamp = TS, tests = T, name = N,
+ testcases = Cases, log = Log, url = Url }) ->
["<testsuite ",
[["package=\"",P,"\" "]||P /= undefined],
- [["hostname=\"",P,"\" "]||H /= undefined],
- [["name=\"",N,"\" "]||N /= undefined],
- [["time=\"",Time,"\" "]||Time /= undefined],
- [["timestamp=\"",TS,"\" "]||TS /= undefined],
+ "hostname=\"",H,"\" "
+ "name=\"",N,"\" "
+ "time=\"",Time,"\" "
+ "timestamp=\"",TS,"\" "
"errors=\"",integer_to_list(E),"\" "
- "tests=\"",integer_to_list(T),"\">",
+ "failures=\"",integer_to_list(F),"\" "
+ "skipped=\"",integer_to_list(S),"\" "
+ "tests=\"",integer_to_list(T),"\" ",
+ [["url=\"",Url,"\" "]||Url /= undefined],
+ "log=\"",Log,"\">",
[to_xml(Case) || Case <- Cases],
"</testsuite>"];
to_xml(#state{ test_suites = TestSuites, axis = Axis, properties = Props }) ->
["<testsuites>",properties_to_xml(Axis,Props),
[to_xml(TestSuite) || TestSuite <- TestSuites],"</testsuites>"].
+properties_to_xml([],[]) ->
+ [];
properties_to_xml(Axis,Props) ->
["<properties>",
[["<property name=\"",Name,"\" axis=\"yes\" value=\"",Value,"\" />"] || {Name,Value} <- Axis],
@@ -217,3 +298,37 @@ sanitize([]) ->
now_to_string(Now) ->
{{YY,MM,DD},{HH,Mi,SS}} = calendar:now_to_local_time(Now),
io_lib:format("~p-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B",[YY,MM,DD,HH,Mi,SS]).
+
+make_url(undefined,_) ->
+ undefined;
+make_url(_,[]) ->
+ undefined;
+make_url(UrlBase0,Log) ->
+ UrlBase = string:strip(UrlBase0,right,$/),
+ RelativeLog = get_relative_log_url(Log),
+ string:join([UrlBase,RelativeLog],"/").
+
+get_test_root(Log) ->
+ LogParts = filename:split(Log),
+ filename:join(lists:sublist(LogParts,1,length(LogParts)-?log_depth)).
+
+get_relative_log_url(Log) ->
+ LogParts = filename:split(Log),
+ Start = length(LogParts)-?log_depth,
+ Length = ?log_depth+1,
+ string:join(lists:sublist(LogParts,Start,Length),"/").
+
+count_tcs([#testcase{name=ConfCase}|TCs],Ok,F,S)
+ when ConfCase=="init_per_suite";
+ ConfCase=="end_per_suite";
+ ConfCase=="init_per_group";
+ ConfCase=="end_per_group" ->
+ count_tcs(TCs,Ok,F,S);
+count_tcs([#testcase{result=passed}|TCs],Ok,F,S) ->
+ count_tcs(TCs,Ok+1,F,S);
+count_tcs([#testcase{result={fail,_}}|TCs],Ok,F,S) ->
+ count_tcs(TCs,Ok,F+1,S);
+count_tcs([#testcase{result={skipped,_}}|TCs],Ok,F,S) ->
+ count_tcs(TCs,Ok,F,S+1);
+count_tcs([],Ok,F,S) ->
+ {Ok+F+S,F,S}.
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index df816f9a61..d469d03e04 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -56,7 +56,8 @@ MODULES= \
ct_snmp_SUITE \
ct_group_leader_SUITE \
ct_cover_SUITE \
- ct_groups_search_SUITE
+ ct_groups_search_SUITE \
+ ct_surefire_SUITE
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/common_test/test/common_test.cover b/lib/common_test/test/common_test.cover
index 66697854ea..3aa49623e7 100644
--- a/lib/common_test/test/common_test.cover
+++ b/lib/common_test/test/common_test.cover
@@ -1,10 +1,10 @@
%% -*- erlang -*-
{incl_app,common_test,details}.
-{cross_apps,common_test,[erl2html2,
- test_server,
- test_server_ctrl,
- test_server_gl,
- test_server_h,
- test_server_io,
- test_server_node,
- test_server_sup]}.
+{cross,common_test,[{test_server,[erl2html2,
+ test_server,
+ test_server_ctrl,
+ test_server_gl,
+ test_server_h,
+ test_server_io,
+ test_server_node,
+ test_server_sup]}]}.
diff --git a/lib/common_test/test/ct_cover_SUITE.erl b/lib/common_test/test/ct_cover_SUITE.erl
index bebfce70d0..cb49dc423f 100644
--- a/lib/common_test/test/ct_cover_SUITE.erl
+++ b/lib/common_test/test/ct_cover_SUITE.erl
@@ -77,7 +77,8 @@ all() ->
slave_start_slave,
cover_node_option,
ct_cover_add_remove_nodes,
- otp_9956
+ otp_9956,
+ cross
].
%%--------------------------------------------------------------------
@@ -161,6 +162,43 @@ otp_9956(Config) ->
check_calls(Events,{?suite,otp_9956,1},1),
ok.
+%% Test cross cover mechanism
+cross(Config) ->
+ {ok,Events1} = run_test(cross1,Config),
+ check_calls(Events1,1),
+
+ CoverFile2 = create_cover_file(cross1,[{cross,[{cross1,[?mod]}]}],Config),
+ {ok,Events2} = run_test(cross2,[{cover,CoverFile2}],Config),
+ check_calls(Events2,1),
+
+ %% Get the log dirs for each test and run cross cover analyse
+ [D11,D12] = lists:sort(get_run_dirs(Events1)),
+ [D21,D22] = lists:sort(get_run_dirs(Events2)),
+
+ ct_cover:cross_cover_analyse(details,[{cross1,D11},{cross2,D21}]),
+ ct_cover:cross_cover_analyse(details,[{cross1,D12},{cross2,D22}]),
+
+ %% Get the cross cover logs and read for each test
+ [C11,C12,C21,C22] =
+ [filename:join(D,"cross_cover.html") || D <- [D11,D12,D21,D22]],
+
+ {ok,CrossData} = file:read_file(C11),
+ {ok,CrossData} = file:read_file(C12),
+
+ {ok,Def} = file:read_file(C21),
+ {ok,Def} = file:read_file(C22),
+
+ %% A simple test: just check that the test module exists in the
+ %% log from cross1 test, and that it does not exist in the log
+ %% from cross2 test.
+ TestMod = list_to_binary(atom_to_list(?mod)),
+ {_,_} = binary:match(CrossData,TestMod),
+ nomatch = binary:match(Def,TestMod),
+ {_,_} = binary:match(Def,
+ <<"No cross cover modules exist for this application">>),
+
+ ok.
+
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
@@ -229,15 +267,18 @@ check_cover(Node) when is_atom(Node) ->
false
end.
+%% Get the log dir "run.<timestamp>" for all (both!) tests
+get_run_dirs(Events) ->
+ [filename:dirname(TCLog) ||
+ {ct_test_support_eh,
+ {event,tc_logfile,_Node,
+ {{?suite,init_per_suite},TCLog}}} <- Events].
+
%% Check that each coverlog includes N calls to ?mod:foo/0
check_calls(Events,N) ->
check_calls(Events,{?mod,foo,0},N).
check_calls(Events,MFA,N) ->
- CoverLogs =
- [filename:join(filename:dirname(TCLog),"all.coverdata") ||
- {ct_test_support_eh,
- {event,tc_logfile,ct@falco,
- {{?suite,init_per_suite},TCLog}}} <- Events],
+ CoverLogs = [filename:join(D,"all.coverdata") || D <- get_run_dirs(Events)],
do_check_logs(CoverLogs,MFA,N).
do_check_logs([CoverLog|CoverLogs],{Mod,_,_} = MFA,N) ->
diff --git a/lib/common_test/test/ct_surefire_SUITE.erl b/lib/common_test/test/ct_surefire_SUITE.erl
new file mode 100644
index 0000000000..69e98cef48
--- /dev/null
+++ b/lib/common_test/test/ct_surefire_SUITE.erl
@@ -0,0 +1,351 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_surefire_SUITE
+%%%
+%%% Description:
+%%% Test cth_surefire hook
+%%%
+%%%-------------------------------------------------------------------
+-module(ct_surefire_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-include_lib("xmerl/include/xmerl.hrl").
+
+-define(eh, ct_test_support_eh).
+
+-define(url_base,"http://my.host.com/").
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ default,
+ absolute_path,
+ relative_path,
+ url,
+ logdir
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+default(Config) when is_list(Config) ->
+ run(default,[cth_surefire],Config),
+ PrivDir = ?config(priv_dir,Config),
+ XmlRe = filename:join([PrivDir,"*","junit_report.xml"]),
+ check_xml(default,XmlRe).
+
+absolute_path(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ Path = filename:join(PrivDir,"abspath.xml"),
+ run(absolute_path,[{cth_surefire,[{path,Path}]}],Config),
+ check_xml(absolute_path,Path).
+
+relative_path(Config) when is_list(Config) ->
+ Path = "relpath.xml",
+ run(relative_path,[{cth_surefire,[{path,Path}]}],Config),
+ PrivDir = ?config(priv_dir,Config),
+ XmlRe = filename:join([PrivDir,"*",Path]),
+ check_xml(relative_path,XmlRe).
+
+url(Config) when is_list(Config) ->
+ Path = "url.xml",
+ run(url,[{cth_surefire,[{url_base,?url_base},
+ {path,Path}]}],Config),
+ PrivDir = ?config(priv_dir,Config),
+ XmlRe = filename:join([PrivDir,"*",Path]),
+ check_xml(url,XmlRe).
+
+logdir(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ LogDir = filename:join(PrivDir,"specific_logdir"),
+ file:make_dir(LogDir),
+ Path = "logdir.xml",
+ run(logdir,[{cth_surefire,[{path,Path}]}],Config,[{logdir,LogDir}]),
+ PrivDir = ?config(priv_dir,Config),
+ XmlRe = filename:join([LogDir,"*",Path]),
+ check_xml(logdir,XmlRe).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+run(Case,CTHs,Config) ->
+ run(Case,CTHs,Config,[]).
+run(Case,CTHs,Config,ExtraOpts) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "surefire_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},{ct_hooks,CTHs},{label,Case}|ExtraOpts],
+ Config),
+ ok = execute(Case, Opts, ERPid, Config).
+
+setup(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts1 =
+ case lists:keymember(logdir,1,Test) of
+ true -> lists:keydelete(logdir,1,Opts0);
+ false -> Opts0
+ end,
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts1 ++ [{event_handler,{?eh,EvHArgs}}|Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+execute(Name, Opts, ERPid, Config) ->
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(Name,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(Name),
+ ct_test_support:verify_events(TestEvents, Events, Config).
+
+reformat(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+test_events(_) ->
+ [{?eh,start_logging,'_'},
+ {?eh,start_info,{1,1,9}},
+ {?eh,tc_start,{surefire_SUITE,init_per_suite}},
+ {?eh,tc_done,{surefire_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{surefire_SUITE,tc_ok}},
+ {?eh,tc_done,{surefire_SUITE,tc_ok,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?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,tc_start,{surefire_SUITE,tc_skip}},
+ {?eh,tc_done,{surefire_SUITE,tc_skip,{skipped,"this test is skipped"}}},
+ {?eh,test_stats,{1,1,{1,0}}},
+ {?eh,tc_start,{surefire_SUITE,tc_autoskip_require}},
+ {?eh,tc_done,{surefire_SUITE,tc_autoskip_require,
+ {skipped,{require_failed,'_'}}}},
+ {?eh,test_stats,{1,1,{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,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,tc_start,{surefire_SUITE,tc_skip}},
+ {?eh,tc_done,{surefire_SUITE,tc_skip,{skipped,"this test is skipped"}}},
+ {?eh,test_stats,{2,2,{2,1}}},
+ {?eh,tc_start,{surefire_SUITE,tc_autoskip_require}},
+ {?eh,tc_done,{surefire_SUITE,tc_autoskip_require,
+ {skipped,{require_failed,'_'}}}},
+ {?eh,test_stats,{2,2,{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,[]}}},
+ {?eh,tc_done,{surefire_SUITE,{init_per_group,g_fail,[]},
+ {failed,{error,all_cases_should_be_skipped}}}},
+ {?eh,tc_auto_skip,{surefire_SUITE,tc_ok,
+ {failed,
+ {surefire_SUITE,init_per_group,
+ {'EXIT',all_cases_should_be_skipped}}}}},
+ {?eh,test_stats,{2,2,{2,3}}},
+ {?eh,tc_auto_skip,{surefire_SUITE,end_per_group,
+ {failed,
+ {surefire_SUITE,init_per_group,
+ {'EXIT',all_cases_should_be_skipped}}}}}],
+ {?eh,tc_start,{surefire_SUITE,end_per_suite}},
+ {?eh,tc_done,{surefire_SUITE,end_per_suite,ok}},
+ {?eh,stop_logging,[]}].
+
+
+%%%-----------------------------------------------------------------
+%%% Check generated xml log files
+check_xml(Case,XmlRe) ->
+ case filelib:wildcard(XmlRe) of
+ [] ->
+ ct:fail("No xml files found with regexp ~p~n", [XmlRe]);
+ [_] = Xmls when Case==absolute_path ->
+ do_check_xml(Case,Xmls);
+ [_,_] = Xmls ->
+ do_check_xml(Case,Xmls)
+ end.
+
+%% Allowed structure:
+%% <testsuites>
+%% <testsuite>
+%% <properties>
+%% <property/>
+%% ...
+%% </properties>
+%% <testcase>
+%% [<failure/> | <error/> | <skipped/> ]
+%% </testcase>
+%% ...
+%% </testsuite>
+%% ...
+%% </testsuites>
+do_check_xml(Case,[Xml|Xmls]) ->
+ ct:log("Checking <a href=~p>~s</a>~n",[Xml,Xml]),
+ {E,_} = xmerl_scan:file(Xml),
+ Expected = events_to_result(lists:flatten(test_events(Case))),
+ ParseResult = testsuites(Case,E),
+ ct:log("Expecting: ~p~n",[[Expected]]),
+ ct:log("Actual : ~p~n",[ParseResult]),
+ [Expected] = ParseResult,
+ do_check_xml(Case,Xmls);
+do_check_xml(_,[]) ->
+ ok.
+
+%% Scanning the XML to get the same type of result as events_to_result/1
+testsuites(Case,#xmlElement{name=testsuites,content=TS}) ->
+ %% OTP-10589 - move properties element to <testsuite>
+ false = lists:keytake(properties,#xmlElement.name,TS),
+ testsuite(Case,TS).
+
+testsuite(Case,[#xmlElement{name=testsuite,content=TC,attributes=A}|TS]) ->
+ {ET,EF,ES} = events_to_numbers(lists:flatten(test_events(Case))),
+ {T,E,F,S} = get_numbers_from_attrs(A,false,false,false,false),
+ ct:log("Expecting total:~p, error:~p, failure:~p, skipped:~p~n",[ET,0,EF,ES]),
+ ct:log("Actual total:~p, error:~p, failure:~p, skipped:~p~n",[T,E,F,S]),
+ {ET,0,EF,ES} = {T,E,F,S},
+
+ %% properties should only be there if given a options to hook
+ false = lists:keytake(properties,#xmlElement.name,TC),
+ %% system-out and system-err is not used by common_test
+ false = lists:keytake('system-out',#xmlElement.name,TC),
+ false = lists:keytake('system-err',#xmlElement.name,TC),
+ R=testcase(Case,TC),
+ [R|testsuite(Case,TS)];
+testsuite(_Case,[]) ->
+ [].
+
+testcase(url=Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) ->
+ R = failed_or_skipped(C),
+ case R of
+ [s] ->
+ case lists:keyfind(url,#xmlAttribute.name,A) of
+ false -> ok;
+ #xmlAttribute{value=UrlAttr} ->
+ lists:keyfind(url,#xmlAttribute.name,A),
+ true = lists:prefix(?url_base,UrlAttr)
+ end;
+ _ ->
+ #xmlAttribute{value=UrlAttr} =
+ lists:keyfind(url,#xmlAttribute.name,A),
+ true = lists:prefix(?url_base,UrlAttr)
+ end,
+ [R|testcase(Case,TC)];
+testcase(Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) ->
+ false = lists:keyfind(url,#xmlAttribute.name,A),
+ R = failed_or_skipped(C),
+ [R|testcase(Case,TC)];
+testcase(_Case,[]) ->
+ [].
+
+failed_or_skipped([#xmlElement{name=failure}|E]) ->
+ [f|failed_or_skipped(E)];
+failed_or_skipped([#xmlElement{name=error}|E]) ->
+ [e|failed_or_skipped(E)];
+failed_or_skipped([#xmlElement{name=skipped}|E]) ->
+ [s|failed_or_skipped(E)];
+failed_or_skipped([]) ->
+ [].
+
+%% Using the expected events to produce the expected result of the XML scanning.
+%% The result is a list of test suites:
+%% Testsuites = [Testsuite]
+%% Testsuite = [Testcase]
+%% Testcase = [] | [f] | [s], indicating ok, failed and skipped respectively
+events_to_result([{?eh,tc_done,{_Suite,_Case,R}}|E]) ->
+ [result(R)|events_to_result(E)];
+events_to_result([{?eh,tc_auto_skip,_}|E]) ->
+ [[s]|events_to_result(E)];
+events_to_result([_|E]) ->
+ events_to_result(E);
+events_to_result([]) ->
+ [].
+
+result(ok) ->[];
+result({skipped,_}) -> [s];
+result({failed,_}) -> [f].
+
+%% Using the expected events' last test_stats element to produce the
+%% expected number of totla, errors, failed and skipped testcases.
+events_to_numbers(E) ->
+ RevE = lists:reverse(E),
+ {?eh,test_stats,{Ok,F,{US,AS}}} = lists:keyfind(test_stats,2,RevE),
+ {Ok+F+US+AS,F,US+AS}.
+
+get_numbers_from_attrs([#xmlAttribute{name=tests,value=X}|A],false,E,F,S) ->
+ get_numbers_from_attrs(A,list_to_integer(X),E,F,S);
+get_numbers_from_attrs([#xmlAttribute{name=errors,value=X}|A],T,false,F,S) ->
+ get_numbers_from_attrs(A,T,list_to_integer(X),F,S);
+get_numbers_from_attrs([#xmlAttribute{name=failures,value=X}|A],T,E,false,S) ->
+ get_numbers_from_attrs(A,T,E,list_to_integer(X),S);
+get_numbers_from_attrs([#xmlAttribute{name=skipped,value=X}|A],T,E,F,false) ->
+ get_numbers_from_attrs(A,T,E,F,list_to_integer(X));
+get_numbers_from_attrs([_|A],T,E,F,S) ->
+ get_numbers_from_attrs(A,T,E,F,S);
+get_numbers_from_attrs([],T,E,F,S) ->
+ {T,E,F,S}.
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
new file mode 100644
index 0000000000..677aee46c5
--- /dev/null
+++ b/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
@@ -0,0 +1,92 @@
+%%--------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%----------------------------------------------------------------------
+%% File: surefire_SUITE.erl
+%%
+%% Description:
+%% This file contains the test cases for cth_surefire.
+%%
+%% @author Support
+%% @doc Test of surefire support in common_test
+%% @end
+%%----------------------------------------------------------------------
+%%----------------------------------------------------------------------
+-module(surefire_SUITE).
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+%% Default timetrap timeout (set in init_per_testcase).
+-define(default_timeout, ?t:minutes(1)).
+
+all() ->
+ testcases() ++ [{group,g},{group,g_fail}].
+
+groups() ->
+ [{g,testcases()},
+ {g_fail,[tc_ok]}].
+
+testcases() ->
+ [tc_ok,
+ tc_fail,
+ tc_skip,
+ tc_autoskip_require].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(Config) ->
+ Config.
+
+init_per_group(g_fail, _Config) ->
+ exit(all_cases_should_be_skipped);
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_Group, Config) ->
+ Config.
+
+init_per_testcase(_Case, Config) ->
+ Dog = test_server:timetrap(?default_timeout),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case, Config) ->
+ Dog=?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Test cases
+break(_Config) ->
+ test_server:break(""),
+ ok.
+
+tc_ok(_Config) ->
+ ok.
+
+tc_fail(_Config) ->
+ ct:fail("this test should fail").
+
+tc_skip(_Config) ->
+ {skip,"this test is skipped"}.
+
+tc_autoskip_require() ->
+ [{require,whatever}].
+tc_autoskip_require(Config) ->
+ ct:fail("this test should never be executed - it should be autoskipped").
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index e5e2e68fcb..fc572aa82f 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -117,11 +117,7 @@ end_per_suite(Config) ->
CTNode = proplists:get_value(ct_node, Config),
PrivDir = proplists:get_value(priv_dir, Config),
true = rpc:call(CTNode, code, del_path, [filename:join(PrivDir,"")]),
- case test_server:is_cover() of
- true -> cover:flush(CTNode);
- false -> ok
- end,
- slave:stop(CTNode),
+ slave_stop(CTNode),
ok.
%%%-----------------------------------------------------------------
@@ -152,11 +148,7 @@ end_per_testcase(_TestCase, Config) ->
case wait_for_ct_stop(CTNode) of
%% Common test was not stopped to we restart node.
false ->
- case test_server:is_cover() of
- true -> cover:flush(CTNode);
- false -> ok
- end,
- slave:stop(CTNode),
+ slave_stop(CTNode),
start_slave(Config,proplists:get_value(trace_level,Config)),
{fail, "Could not stop common_test"};
true ->
@@ -1274,3 +1266,22 @@ rm_files([F | Fs]) ->
rm_files([]) ->
ok.
+%%%-----------------------------------------------------------------
+%%%
+slave_stop(Node) ->
+ Cover = test_server:is_cover(),
+ if Cover-> cover:flush(Node);
+ true -> ok
+ end,
+ erlang:monitor_node(Node, true),
+ slave:stop(Node),
+ receive
+ {nodedown, Node} ->
+ if Cover -> cover:stop(Node);
+ true -> ok
+ end
+ after 5000 ->
+ erlang:monitor_node(Node, false),
+ receive {nodedown, Node} -> ok after 0 -> ok end %flush
+ end,
+ ok.
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index df1af36eeb..10e7f5e9ce 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -248,6 +248,7 @@ format_error({module_name,Mod,Filename}) ->
abstract_code=[], %Abstract code for debugger.
options=[] :: [option()], %Options for compilation
mod_options=[] :: [option()], %Options for module_info
+ encoding=none :: none | epp:source_coding(),
errors=[],
warnings=[]}).
@@ -734,8 +735,9 @@ collect_asm([X | Rest], R) ->
beam_consult_asm(St) ->
case file:consult(St#compile.ifile) of
{ok, Forms0} ->
+ Encoding = epp:read_encoding(St#compile.ifile),
{Module, Forms} = preprocess_asm_forms(Forms0),
- {ok,St#compile{module=Module, code=Forms}};
+ {ok,St#compile{module=Module, code=Forms, encoding=Encoding}};
{error,E} ->
Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
{error,St#compile{errors=St#compile.errors ++ Es}}
@@ -777,7 +779,8 @@ parse_module(St) ->
R = epp:parse_file(St#compile.ifile, IncludePath, pre_defs(Opts)),
case R of
{ok,Forms} ->
- {ok,St#compile{code=Forms}};
+ Encoding = epp:read_encoding(St#compile.ifile),
+ {ok,St#compile{code=Forms,encoding=Encoding}};
{error,E} ->
Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
{error,St#compile{errors=St#compile.errors ++ Es}}
@@ -1339,16 +1342,12 @@ save_binary(#compile{code=none}=St) -> {ok,St};
save_binary(#compile{module=Mod,ofile=Outfile,
options=Opts}=St) ->
%% Test that the module name and output file name match.
- %% We must take care to not completely break a packaged module
- %% (even though packages still is as an experimental, unsupported
- %% feature) - so we will extract the last part of a packaged
- %% module name and compare only that.
case member(no_error_module_mismatch, Opts) of
true ->
save_binary_1(St);
false ->
Base = filename:rootname(filename:basename(Outfile)),
- case lists:last(packages:split(Mod)) of
+ case atom_to_list(Mod) of
Base ->
save_binary_1(St);
_ ->
@@ -1424,28 +1423,28 @@ report_warnings(#compile{options=Opts,warnings=Ws0}) ->
end.
format_message(F, P, [{{Line,Column}=Loc,Mod,E}|Es]) ->
- M = {{F,Loc},io_lib:format("~s:~w:~w ~s~s\n",
+ M = {{F,Loc},io_lib:format("~s:~w:~w ~s~ts\n",
[F,Line,Column,P,Mod:format_error(E)])},
[M|format_message(F, P, Es)];
format_message(F, P, [{Line,Mod,E}|Es]) ->
- M = {{F,{Line,0}},io_lib:format("~s:~w: ~s~s\n",
+ M = {{F,{Line,0}},io_lib:format("~s:~w: ~s~ts\n",
[F,Line,P,Mod:format_error(E)])},
[M|format_message(F, P, Es)];
format_message(F, P, [{Mod,E}|Es]) ->
- M = {none,io_lib:format("~s: ~s~s\n", [F,P,Mod:format_error(E)])},
+ M = {none,io_lib:format("~s: ~s~ts\n", [F,P,Mod:format_error(E)])},
[M|format_message(F, P, Es)];
format_message(_, _, []) -> [].
%% list_errors(File, ErrorDescriptors) -> ok
list_errors(F, [{{Line,Column},Mod,E}|Es]) ->
- io:fwrite("~s:~w:~w: ~s\n", [F,Line,Column,Mod:format_error(E)]),
+ io:fwrite("~s:~w:~w: ~ts\n", [F,Line,Column,Mod:format_error(E)]),
list_errors(F, Es);
list_errors(F, [{Line,Mod,E}|Es]) ->
- io:fwrite("~s:~w: ~s\n", [F,Line,Mod:format_error(E)]),
+ io:fwrite("~s:~w: ~ts\n", [F,Line,Mod:format_error(E)]),
list_errors(F, Es);
list_errors(F, [{Mod,E}|Es]) ->
- io:fwrite("~s: ~s\n", [F,Mod:format_error(E)]),
+ io:fwrite("~s: ~ts\n", [F,Mod:format_error(E)]),
list_errors(F, Es);
list_errors(_F, []) -> ok.
@@ -1501,10 +1500,12 @@ src_listing(Ext, St) ->
Ext, St).
do_src_listing(Lf, Fs) ->
- foreach(fun (F) -> io:put_chars(Lf, [erl_pp:form(F),"\n"]) end,
+ Opts = [lists:keyfind(encoding, 1, io:getopts(Lf))],
+ foreach(fun (F) -> io:put_chars(Lf, [erl_pp:form(F, Opts),"\n"]) end,
Fs).
-listing(Ext, St) ->
+listing(Ext, St0) ->
+ St = St0#compile{encoding = none},
listing(fun(Lf, Fs) -> beam_listing:module(Lf, Fs) end, Ext, St).
listing(LFun, Ext, St) ->
@@ -1512,6 +1513,7 @@ listing(LFun, Ext, St) ->
case file:open(Lfile, [write,delayed_write]) of
{ok,Lf} ->
Code = restore_expanded_types(Ext, St#compile.code),
+ output_encoding(Lf, St),
LFun(Lf, Code),
ok = file:close(Lf),
{ok,St};
@@ -1520,6 +1522,12 @@ listing(LFun, Ext, St) ->
{error,St#compile{errors=St#compile.errors ++ Es}}
end.
+output_encoding(F, #compile{encoding = none}) ->
+ ok = io:setopts(F, [{encoding, epp:default_encoding()}]);
+output_encoding(F, #compile{encoding = Encoding}) ->
+ ok = io:setopts(F, [{encoding, Encoding}]),
+ ok = io:fwrite(F, <<"%% ~s\n">>, [epp:encoding_to_string(Encoding)]).
+
restore_expanded_types("P", Fs) ->
epp:restore_typed_record_fields(Fs);
restore_expanded_types("E", {M,I,Fs0}) ->
diff --git a/lib/compiler/src/core_scan.erl b/lib/compiler/src/core_scan.erl
index 5aab8ae855..0ca2f57dde 100644
--- a/lib/compiler/src/core_scan.erl
+++ b/lib/compiler/src/core_scan.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -31,16 +32,16 @@
%% 173 - 176 { - ~ punctuation
%% 177 DEL control
%% 200 - 237 control
-%% 240 - 277 NBSP - � punctuation
-%% 300 - 326 � - � uppercase
-%% 327 � punctuation
-%% 330 - 336 � - � uppercase
-%% 337 - 366 � - � lowercase
-%% 367 � punctuation
-%% 370 - 377 � - � lowercase
+%% 240 - 277 NBSP - ¿ punctuation
+%% 300 - 326 À - Ö uppercase
+%% 327 × punctuation
+%% 330 - 336 Ø - Þ uppercase
+%% 337 - 366 ß - ö lowercase
+%% 367 ÷ punctuation
+%% 370 - 377 ø - ÿ lowercase
%%
%% Many punctuation characters region have special meaning. Must
-%% watch using � \327, bvery close to x \170
+%% watch using × \327, bvery close to x \170
-module(core_scan).
@@ -239,11 +240,11 @@ scan1([C|Cs], Toks, Pos) when C >= $\200, C =< $\240 ->
scan1(Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $a, C =< $z -> %Keywords
scan_key_word(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
+scan1([C|Cs], Toks, Pos) when C >= $ß, C =< $ÿ, C /= $÷ ->
scan_key_word(C, Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $A, C =< $Z -> %Variables
scan_variable(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
+scan1([C|Cs], Toks, Pos) when C >= $À, C =< $Þ, C /= $× ->
scan_variable(C, Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Numbers
scan_number(C, Cs, Toks, Pos);
@@ -308,9 +309,9 @@ scan_name([], Ncs) ->
{Ncs,[]}.
name_char(C) when C >= $a, C =< $z -> true;
-name_char(C) when C >= $�, C =< $�, C /= $� -> true;
+name_char(C) when C >= $ß, C =< $ÿ, C /= $÷ -> true;
name_char(C) when C >= $A, C =< $Z -> true;
-name_char(C) when C >= $�, C =< $�, C /= $� -> true;
+name_char(C) when C >= $À, C =< $Þ, C /= $× -> true;
name_char(C) when C >= $0, C =< $9 -> true;
name_char($_) -> true;
name_char($@) -> true;
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index e55fb2a037..a8c69c3cb1 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -35,10 +35,8 @@
-record(expand, {module=[], %Module name
parameters=undefined, %Module parameters
- package="", %Module package
exports=[], %Exports
imports=[], %Imports
- mod_imports, %Module Imports
compile=[], %Compile flags
attributes=[], %Attributes
callbacks=[], %Callbacks
@@ -67,12 +65,8 @@ module(Fs0, Opts0) ->
%% Set pre-defined exported functions.
PreExp = [{module_info,0},{module_info,1}],
- %% Set pre-defined module imports.
- PreModImp = [{erlang,erlang},{packages,packages}],
-
%% Build initial expand record.
St0 = #expand{exports=PreExp,
- mod_imports=dict:from_list(PreModImp),
compile=Opts,
defined=PreExp,
bitdefault = erl_bits:system_bitdefault(),
@@ -242,14 +236,12 @@ forms([], St) -> {[],St}.
%% Process an attribute, this just affects the state.
attribute(module, {Module, As}, _L, St) ->
- M = package_to_string(Module),
- St#expand{module=list_to_atom(M),
- package=packages:strip_last(M),
+ true = is_atom(Module),
+ St#expand{module=Module,
parameters=As};
attribute(module, Module, _L, St) ->
- M = package_to_string(Module),
- St#expand{module=list_to_atom(M),
- package=packages:strip_last(M)};
+ true = is_atom(Module),
+ St#expand{module=Module};
attribute(export, Es, _L, St) ->
St#expand{exports=union(from_list(Es), St#expand.exports)};
attribute(import, Is, _L, St) ->
@@ -312,8 +304,6 @@ pattern({tuple,Line,Ps}, St0) ->
%%pattern({struct,Line,Tag,Ps}, St0) ->
%% {TPs,TPsvs,St1} = pattern_list(Ps, St0),
%% {{tuple,Line,[{atom,Line,Tag}|TPs]},TPsvs,St1};
-pattern({record_field,_,_,_}=M, St) ->
- {expand_package(M, St),St}; % must be a package name
pattern({bin,Line,Es0}, St0) ->
{Es1,St1} = pattern_bin(Es0, St0),
{{bin,Line,Es1},St1};
@@ -404,8 +394,6 @@ expr({tuple,Line,Es0}, St0) ->
%%expr({struct,Line,Tag,Es0}, Vs, St0) ->
%% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0),
%% {{tuple,Line,[{atom,Line,Tag}|Es1]},Esvs,Esus,St1};
-expr({record_field,_,_,_}=M, St) ->
- {expand_package(M, St),St}; % must be a package name
expr({bin,Line,Es0}, St0) ->
{Es1,St1} = expr_bin(Es0, St0),
{{bin,Line,Es1},St1};
@@ -448,12 +436,9 @@ expr({call,Line,{atom,La,N}=Atom,As0}, St0) ->
end
end
end;
-expr({call,Line,{record_field,_,_,_}=M,As0}, St0) ->
- expr({call,Line,expand_package(M, St0),As0}, St0);
-expr({call,Line,{remote,Lr,M,F},As0}, St0) ->
- M1 = expand_package(M, St0),
- {[M2,F1|As1],St1} = expr_list([M1,F|As0], St0),
- {{call,Line,{remote,Lr,M2,F1},As1},St1};
+expr({call,Line,{remote,Lr,M0,F},As0}, St0) ->
+ {[M1,F1|As1],St1} = expr_list([M0,F|As0], St0),
+ {{call,Line,{remote,Lr,M1,F1},As1},St1};
expr({call,Line,F,As0}, St0) ->
{[Fun1|As1],St1} = expr_list([F|As0], St0),
{{call,Line,Fun1,As1},St1};
@@ -666,32 +651,6 @@ string_to_conses(Line, Cs, Tail) ->
foldr(fun (C, T) -> {cons,Line,{char,Line,C},T} end, Tail, Cs).
-%% In syntax trees, module/package names are atoms or lists of atoms.
-
-package_to_string(A) when is_atom(A) -> atom_to_list(A);
-package_to_string(L) when is_list(L) -> packages:concat(L).
-
-expand_package({atom,L,A} = M, St) ->
- case dict:find(A, St#expand.mod_imports) of
- {ok, A1} ->
- {atom,L,A1};
- error ->
- case packages:is_segmented(A) of
- true ->
- M;
- false ->
- M1 = packages:concat(St#expand.package, A),
- {atom,L,list_to_atom(M1)}
- end
- end;
-expand_package(M, _St) ->
- case erl_parse:package_segments(M) of
- error ->
- M;
- M1 ->
- {atom,element(2,M),list_to_atom(package_to_string(M1))}
- end.
-
%% import(Line, Imports, State) ->
%% State'
%% imported(Name, Arity, State) ->
@@ -699,15 +658,10 @@ expand_package(M, _St) ->
%% Handle import declarations and test for imported functions. No need to
%% check when building imports as code is correct.
-import({Mod0,Fs}, St) ->
- Mod = list_to_atom(package_to_string(Mod0)),
+import({Mod,Fs}, St) ->
+ true = is_atom(Mod),
Mfs = from_list(Fs),
- St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)};
-import(Mod0, St) ->
- Mod = package_to_string(Mod0),
- Key = list_to_atom(packages:last(Mod)),
- St#expand{mod_imports=dict:store(Key, list_to_atom(Mod),
- St#expand.mod_imports)}.
+ St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}.
add_imports(Mod, [F|Fs], Is) ->
add_imports(Mod, Fs, orddict:store(F, Mod, Is));
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index bec97b0199..f8f74e6f7a 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -44,7 +44,7 @@ groups() ->
{group,vsn},otp_2380,otp_2141,otp_2173,otp_4790,
const_list_256,bin_syntax_1,bin_syntax_2,
bin_syntax_3,bin_syntax_4,bin_syntax_5,bin_syntax_6,
- live_var,convopts,bad_functional_value,
+ live_var,convopts,
catch_in_catch,redundant_case,long_string,otp_5076,
complex_guard,otp_5092,otp_5151,otp_5235,otp_5244,
trycatch_4,opt_crash,otp_5404,otp_5436,otp_5481,
@@ -143,7 +143,6 @@ split({int, N}, <<N:16,B:N/binary,T/binary>>) ->
?comp(live_var).
?comp(trycatch_4).
-?comp(bad_functional_value).
?comp(catch_in_catch).
diff --git a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl b/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl
deleted file mode 100644
index 126a573e83..0000000000
--- a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl
+++ /dev/null
@@ -1,28 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(bad_functional_value).
-
--export([?MODULE/0,a/0]).
-
-?MODULE() ->
- ok.
-
-a() ->
- .list_to_atom("ok").
-
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 2cd75944f4..229e5a98a1 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -27,7 +27,7 @@
app_test/1,
file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1,
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
- other_output/1, package_forms/1, encrypted_abstr/1,
+ other_output/1, encrypted_abstr/1,
bad_record_use1/1, bad_record_use2/1, strict_record/1,
missing_testheap/1, cover/1, env/1, core/1, asm/1,
sys_pre_attributes/1]).
@@ -44,7 +44,7 @@ all() ->
test_lib:recompile(?MODULE),
[app_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
- other_output, package_forms, encrypted_abstr,
+ other_output, encrypted_abstr,
{group, bad_record_use}, strict_record,
missing_testheap, cover, env, core, asm,
sys_pre_attributes].
@@ -410,32 +410,6 @@ other_output(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
-package_forms(Config) when is_list(Config) ->
- Fs = [{attribute,1,file,{"./p.erl",1}},
- {attribute,1,module,[p,p]},
- {attribute,3,compile,export_all},
- {attribute,1,file,
- {"/clearcase/otp/erts/lib/stdlib/include/qlc.hrl",1}},
- {attribute,6,file,{"./p.erl",6}},
- {function,7,q,0,
- [{clause,7,[],[],
- [{call,8,
- {remote,8,{atom,8,qlc},{atom,8,q}},
- [{tuple,-8,
- [{atom,-8,qlc_lc},
- {'fun',-8,
- {clauses,
- [{clause,-8,[],[],
- [{tuple,-8,
- [{atom,-8,simple_v1},
- {atom,-8,'X'},
- {'fun',-8,{clauses,[{clause,-8,[],[],[{nil,8}]}]}},
- {integer,-8,8}]}]}]}},
- {atom,-8,undefined}]}]}]}]},
- {eof,9}],
- {ok,'p.p',_} = compile:forms(Fs, ['S',report]),
- ok.
-
encrypted_abstr(Config) when is_list(Config) ->
?line Dog = test_server:timetrap(test_server:minutes(10)),
?line {Simple,Target} = files(Config, "encrypted_abstr"),
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 72c9e5b8e8..e77e5fb8f0 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -44,6 +44,7 @@
#include <openssl/md5.h>
#include <openssl/md4.h>
#include <openssl/sha.h>
+#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#include <openssl/rc4.h>
@@ -139,6 +140,10 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -246,6 +251,10 @@ static ErlNifFunc nif_funcs[] = {
{"md5_init", 0, md5_init},
{"md5_update", 2, md5_update},
{"md5_final", 1, md5_final},
+ {"ripemd160", 1, ripemd160},
+ {"ripemd160_init", 0, ripemd160_init},
+ {"ripemd160_update", 2, ripemd160_update},
+ {"ripemd160_final", 1, ripemd160_final},
{"sha", 1, sha},
{"sha_init", 0, sha_init},
{"sha_update", 2, sha_update},
@@ -326,6 +335,8 @@ ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload)
#define MD5_LEN_96 12
#define MD4_CTX_LEN (sizeof(MD4_CTX))
#define MD4_LEN 16
+#define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX))
+#define RIPEMD160_LEN 20
#define SHA_CTX_LEN (sizeof(SHA_CTX))
#define SHA_LEN 20
#define SHA_LEN_96 12
@@ -600,6 +611,53 @@ static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return ret;
}
+static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Data) */
+ ErlNifBinary ibin;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
+ return enif_make_badarg(env);
+ }
+ RIPEMD160((unsigned char *) ibin.data, ibin.size,
+ enif_make_new_binary(env,RIPEMD160_LEN, &ret));
+ return ret;
+}
+static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+ ERL_NIF_TERM ret;
+ RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret));
+ return ret;
+}
+static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+ RIPEMD160_CTX* new_ctx;
+ ErlNifBinary ctx_bin, data_bin;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin)
+ || ctx_bin.size != RIPEMD160_CTX_LEN
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret);
+ memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN);
+ RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size);
+ return ret;
+}
+static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context) */
+ ErlNifBinary ctx_bin;
+ RIPEMD160_CTX ctx_clone;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */
+ RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone);
+ return ret;
+}
+
+
static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data) */
ErlNifBinary ibin;
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 3e533158c8..61e80d7d5f 100644..100755
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -265,7 +265,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<name>hash(Type, Data) -> Digest</name>
<fsummary></fsummary>
<type>
- <v>Type = md4 | md5 | sha | sha224 | sha256 | sha384 | sha512</v>
+ <v>Type = md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512</v>
<v>Data = iodata()</v>
<v>Digest = binary()</v>
</type>
@@ -279,7 +279,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<name>hash_init(Type) -> Context</name>
<fsummary></fsummary>
<type>
- <v>Type = md4 | md5 | sha | sha224 | sha256 | sha384 | sha512</v>
+ <v>Type = md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512</v>
</type>
<desc>
<p>Initializes the context for streaming hash operations. <c>Type</c> determines
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 461558a79e..f25d63fe3b 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -197,43 +197,48 @@ version() -> ?CRYPTO_VSN.
%%
-spec hash(_, iodata()) -> binary().
-hash(md5, Data) -> md5(Data);
-hash(md4, Data) -> md4(Data);
-hash(sha, Data) -> sha(Data);
-hash(sha224, Data) -> sha224(Data);
-hash(sha256, Data) -> sha256(Data);
-hash(sha384, Data) -> sha384(Data);
-hash(sha512, Data) -> sha512(Data).
-
--spec hash_init('md5'|'md4'|'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
-
-hash_init(md5) -> {md5, md5_init()};
-hash_init(md4) -> {md4, md4_init()};
-hash_init(sha) -> {sha, sha_init()};
-hash_init(sha224) -> {sha224, sha224_init()};
-hash_init(sha256) -> {sha256, sha256_init()};
-hash_init(sha384) -> {sha384, sha384_init()};
-hash_init(sha512) -> {sha512, sha512_init()}.
+hash(md5, Data) -> md5(Data);
+hash(md4, Data) -> md4(Data);
+hash(sha, Data) -> sha(Data);
+hash(ripemd160, Data) -> ripemd160(Data);
+hash(sha224, Data) -> sha224(Data);
+hash(sha256, Data) -> sha256(Data);
+hash(sha384, Data) -> sha384(Data);
+hash(sha512, Data) -> sha512(Data).
+
+-spec hash_init('md5'|'md4'|'ripemd160'|
+ 'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
+
+hash_init(md5) -> {md5, md5_init()};
+hash_init(md4) -> {md4, md4_init()};
+hash_init(sha) -> {sha, sha_init()};
+hash_init(ripemd160) -> {ripemd160, ripemd160_init()};
+hash_init(sha224) -> {sha224, sha224_init()};
+hash_init(sha256) -> {sha256, sha256_init()};
+hash_init(sha384) -> {sha384, sha384_init()};
+hash_init(sha512) -> {sha512, sha512_init()}.
-spec hash_update(_, iodata()) -> any().
-hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
-hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
-hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
-hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
-hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
-hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
-hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
+hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
+hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
+hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)};
+hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
+hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
+hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
+hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
-spec hash_final(_) -> binary().
-hash_final({md5,Context}) -> md5_final(Context);
-hash_final({md4,Context}) -> md4_final(Context);
-hash_final({sha,Context}) -> sha_final(Context);
-hash_final({sha224,Context}) -> sha224_final(Context);
-hash_final({sha256,Context}) -> sha256_final(Context);
-hash_final({sha384,Context}) -> sha384_final(Context);
-hash_final({sha512,Context}) -> sha512_final(Context).
+hash_final({md5,Context}) -> md5_final(Context);
+hash_final({md4,Context}) -> md4_final(Context);
+hash_final({sha,Context}) -> sha_final(Context);
+hash_final({ripemd160,Context}) -> ripemd160_final(Context);
+hash_final({sha224,Context}) -> sha224_final(Context);
+hash_final({sha256,Context}) -> sha256_final(Context);
+hash_final({sha384,Context}) -> sha384_final(Context);
+hash_final({sha512,Context}) -> sha512_final(Context).
%%
%% MD5
@@ -263,6 +268,20 @@ md4_update(_Context, _Data) -> ?nif_stub.
md4_final(_Context) -> ?nif_stub.
%%
+%% RIPEMD160
+%%
+
+-spec ripemd160(iodata()) -> binary().
+-spec ripemd160_init() -> binary().
+-spec ripemd160_update(binary(), iodata()) -> binary().
+-spec ripemd160_final(binary()) -> binary().
+
+ripemd160(_Data) -> ?nif_stub.
+ripemd160_init() -> ?nif_stub.
+ripemd160_update(_Context, _Data) -> ?nif_stub.
+ripemd160_final(_Context) -> ?nif_stub.
+
+%%
%% SHA
%%
-spec sha(iodata()) -> binary().
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 8965ab6b94..019f5f9d83 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -39,6 +39,8 @@
hmac_update_md5_io/1,
hmac_update_md5_n/1,
hmac_rfc4231/1,
+ ripemd160/1,
+ ripemd160_update/1,
sha256/1,
sha256_update/1,
sha512/1,
@@ -86,7 +88,7 @@ groups() ->
[{info, [sequence],[info, {group, rest}]},
{rest, [],
[md5, md5_update, md4, md4_update, md5_mac,
- md5_mac_io, sha, sha_update,
+ md5_mac_io, ripemd160, ripemd160_update, sha, sha_update,
sha256, sha256_update, sha512, sha512_update,
hmac_update_sha, hmac_update_sha_n, hmac_update_sha256, hmac_update_sha512,
hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5,
@@ -719,7 +721,33 @@ hmac_update_md5_n(Config) when is_list(Config) ->
?line Mac = crypto:hmac_final_n(Ctx3, 12),
?line Exp = crypto:md5_mac_96(Key, lists:flatten([Data, Data2])),
?line m(Exp, Mac).
-
+%%
+%%
+ripemd160(doc) ->
+ ["Generate RIPEMD160 message digests and check the result."];
+ripemd160(suite) ->
+ [];
+ripemd160(Config) when is_list(Config) ->
+ ?line m(crypto:hash(ripemd160,"abc"),
+ hexstr2bin("8EB208F7E05D987A9B044A8E98C6B087F15A0BFC")),
+ ?line m(crypto:hash(ripemd160,"abcdbcdecdefdefgefghfghighijhijkijkljklmklm"
+ "nlmnomnopnopq"),
+ hexstr2bin("12A053384A9C0C88E405A06C27DCF49ADA62EB2B")).
+
+
+%%
+%%
+ripemd160_update(doc) ->
+ ["Generate RIPEMD160 message digests by using ripemd160_init,"
+ "ripemd160_update, and ripemd160_final and check the result."];
+ripemd160_update(suite) ->
+ [];
+ripemd160_update(Config) when is_list(Config) ->
+ ?line Ctx = crypto:hash_init(ripemd160),
+ ?line Ctx1 = crypto:hash_update(Ctx, "abcdbcdecdefdefgefghfghighi"),
+ ?line Ctx2 = crypto:hash_update(Ctx1, "jhijkijkljklmklmnlmnomnopnopq"),
+ ?line m(crypto:hash_final(Ctx2),
+ hexstr2bin("12A053384A9C0C88E405A06C27DCF49ADA62EB2B")).
%%
%%
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index 2e88c35741..5e5948c965 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1248,7 +1248,7 @@ if_clauses([], Bs, Ieval) ->
exception(error, if_clause, Bs, Ieval).
%% case_clauses(Value, Clauses, Bindings, Error, Ieval)
-%% Error = try_clause � case_clause
+%% Error = try_clause | case_clause
case_clauses(Val, [{clause,_,[P],G,B}|Cs], Bs0, Error, Ieval) ->
case match(P, Val, Bs0) of
{match,Bs} ->
diff --git a/lib/debugger/src/dbg_ui_trace.erl b/lib/debugger/src/dbg_ui_trace.erl
index d318987f60..8017069c50 100644
--- a/lib/debugger/src/dbg_ui_trace.erl
+++ b/lib/debugger/src/dbg_ui_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -31,10 +31,10 @@
pid, % pid() Debugged process
meta, % pid() Meta process
- status, % {Status,Mod,Line} � {exit,Where,Reason}
- % Status = init � idle | break
- % | wait_break � wait_running
- % � running
+ status, % {Status,Mod,Line} | {exit,Where,Reason}
+ % Status = init | idle | break
+ % | wait_break | wait_running
+ % | running
% Where={Mod,Line} | null
cm, % atom() | undefined Current module
@@ -718,7 +718,7 @@ menus() ->
%% enable(Status) -> [MenuItem]
%% Status = init % when first message from Meta has arrived
-%% | idle | break | exit | wait_break � wait_running | running
+%% | idle | break | exit | wait_break | wait_running | running
enable(init) -> [];
enable(idle) -> ['Stop','Kill'];
enable(break) -> ['Step','Next','Continue','Finish','Skip',
diff --git a/lib/debugger/src/dbg_ui_trace_win.erl b/lib/debugger/src/dbg_ui_trace_win.erl
index 1b439cbf18..beb3fbd71e 100644
--- a/lib/debugger/src/dbg_ui_trace_win.erl
+++ b/lib/debugger/src/dbg_ui_trace_win.erl
@@ -418,8 +418,8 @@ clear_breaks(WinInfo, Mod) ->
%%--------------------------------------------------------------------
%% display(Arg)
%% Arg = idle | {Status,Mod,Line} | {running,Mod}
-%% � {exit,Where,Reason} | {text,Text}
-%% Status = break | wait � Level
+%% | {exit,Where,Reason} | {text,Text}
+%% Status = break | wait | Level
%% Level = int()
%% Mod = atom()
%% Line = integer()
diff --git a/lib/debugger/src/dbg_wx_trace.erl b/lib/debugger/src/dbg_wx_trace.erl
index 2fdf39ba5a..f61df93aec 100644
--- a/lib/debugger/src/dbg_wx_trace.erl
+++ b/lib/debugger/src/dbg_wx_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -32,10 +32,10 @@
pid, % pid() Debugged process
meta, % pid() Meta process
- status, % {Status,Mod,Line} � {exit,Where,Reason}
- % Status = init � idle | break
- % | wait_break � wait_running
- % � running
+ status, % {Status,Mod,Line} | {exit,Where,Reason}
+ % Status = init | idle | break
+ % | wait_break | wait_running
+ % | running
% Where={Mod,Line} | null
cm, % atom() | undefined Current module
@@ -740,7 +740,7 @@ menus() ->
%% enable(Status) -> [MenuItem]
%% Status = init % when first message from Meta has arrived
-%% | idle | break | exit | wait_break � wait_running | running
+%% | idle | break | exit | wait_break | wait_running | running
enable(init) -> [];
enable(idle) -> ['Stop','Kill'];
enable(break) -> ['Step','Next','Continue','Finish','Skip',
diff --git a/lib/debugger/src/dbg_wx_trace_win.erl b/lib/debugger/src/dbg_wx_trace_win.erl
index 68e8e0b844..40d110f071 100644
--- a/lib/debugger/src/dbg_wx_trace_win.erl
+++ b/lib/debugger/src/dbg_wx_trace_win.erl
@@ -431,8 +431,8 @@ clear_breaks(WinInfo, Mod) ->
%%--------------------------------------------------------------------
%% display(Arg)
%% Arg = idle | {Status,Mod,Line} | {running,Mod}
-%% � {exit,Where,Reason} | {text,Text}
-%% Status = break | wait � Level
+%% | {exit,Where,Reason} | {text,Text}
+%% Status = break | wait | Level
%% Level = int()
%% Mod = atom()
%% Line = integer()
diff --git a/lib/debugger/src/int.erl b/lib/debugger/src/int.erl
index b3a8a07f03..1c9f2eddd1 100644
--- a/lib/debugger/src/int.erl
+++ b/lib/debugger/src/int.erl
@@ -626,18 +626,18 @@ find_src(Beam) ->
find_beam(Mod, Src) ->
SrcDir = filename:dirname(Src),
- BeamFile = packages:last(Mod) ++ code:objfile_extension(),
+ BeamFile = atom_to_list(Mod) ++ code:objfile_extension(),
File = filename:join(SrcDir, BeamFile),
case is_file(File) of
true -> File;
- false -> find_beam_1(Mod, SrcDir)
+ false -> find_beam_1(Mod, BeamFile, SrcDir)
end.
-find_beam_1(Mod, SrcDir) ->
- RootDir = find_root_dir(SrcDir, packages:first(Mod)),
+find_beam_1(Mod, BeamFile, SrcDir) ->
+ RootDir = filename:dirname(SrcDir),
EbinDir = filename:join(RootDir, "ebin"),
CodePath = [EbinDir | code:get_path()],
- BeamFile = to_path(Mod) ++ code:objfile_extension(),
+ BeamFile = atom_to_list(Mod) ++ code:objfile_extension(),
lists:foldl(fun(_, Beam) when is_list(Beam) -> Beam;
(Dir, error) ->
File = filename:join(Dir, BeamFile),
@@ -649,14 +649,6 @@ find_beam_1(Mod, SrcDir) ->
error,
CodePath).
-to_path(X) ->
- filename:join(packages:split(X)).
-
-find_root_dir(Dir, [_|Ss]) ->
- find_root_dir(filename:dirname(Dir), Ss);
-find_root_dir(Dir, []) ->
- filename:dirname(Dir).
-
check_beam(BeamBin) when is_binary(BeamBin) ->
case beam_lib:chunks(BeamBin, [abstract_code,exports]) of
{ok,{_Mod,[{abstract_code,no_abstract_code}|_]}} ->
@@ -711,14 +703,11 @@ scan_module_name_2(_, _) ->
scan_module_name_3(Ts) ->
case erl_parse:parse_form(Ts) of
- {ok, {attribute,_,module,{M,_}}} -> module_atom(M);
- {ok, {attribute,_,module,M}} -> module_atom(M);
+ {ok, {attribute,_,module,{M,_}}} -> M;
+ {ok, {attribute,_,module,M}} -> M;
_ -> error
end.
-module_atom(A) when is_atom(A) -> A;
-module_atom(L) when is_list(L) -> list_to_atom(packages:concat(L)).
-
%%--Stop interpreting modules-----------------------------------------
del_mod(AbsMod, Dist) ->
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index 4080dfdf77..5e0c9b51e3 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>2011</year>
+ <year>2006</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -288,7 +288,11 @@ Option :: {files, [Filename :: string()]}
| {include_dirs, [DirName :: string()]}
| {output_file, FileName :: string()}
| {output_plt, FileName :: string()}
- | {analysis_type, 'succ_typings' | 'plt_add' | 'plt_build' | 'plt_check' | 'plt_remove'}
+ | {analysis_type, 'succ_typings' |
+ 'plt_add' |
+ 'plt_build' |
+ 'plt_check' |
+ 'plt_remove'}
| {warnings, [WarnOpts]}
| {get_warnings, bool()}
diff --git a/lib/dialyzer/doc/src/dialyzer_chapter.xml b/lib/dialyzer/doc/src/dialyzer_chapter.xml
index d15069991e..be75f1cc65 100644
--- a/lib/dialyzer/doc/src/dialyzer_chapter.xml
+++ b/lib/dialyzer/doc/src/dialyzer_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2009</year>
+ <year>2006</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -140,7 +140,9 @@
<code type="none">
- dialyzer --build_plt -r $ERL_TOP/lib/stdlib/ebin $ERL_TOP/lib/kernel/ebin $ERL_TOP/lib/mnesia/ebin
+ dialyzer --build_plt -r $ERL_TOP/lib/stdlib/ebin\
+ $ERL_TOP/lib/kernel/ebin \
+ $ERL_TOP/lib/mnesia/ebin
</code>
<p>Dialyzer will look if there is an environment variable called
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl
index a97270b9f3..f4e609bf5b 100644
--- a/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/core_scan.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%% ``The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
@@ -30,16 +31,16 @@
%% 173 - 176 { - ~ punctuation
%% 177 DEL control
%% 200 - 237 control
-%% 240 - 277 NBSP - � punctuation
-%% 300 - 326 � - � uppercase
-%% 327 � punctuation
-%% 330 - 336 � - � uppercase
-%% 337 - 366 � - � lowercase
-%% 367 � punctuation
-%% 370 - 377 � - � lowercase
+%% 240 - 277 NBSP - ¿ punctuation
+%% 300 - 326 À - Ö uppercase
+%% 327 × punctuation
+%% 330 - 336 Ø - Þ uppercase
+%% 337 - 366 ß - ö lowercase
+%% 367 ÷ punctuation
+%% 370 - 377 ø - ÿ lowercase
%%
%% Many punctuation characters region have special meaning. Must
-%% watch using � \327, bvery close to x \170
+%% watch using × \327, bvery close to x \170
-module(core_scan).
@@ -266,11 +267,11 @@ scan1([C|Cs], Toks, Pos) when C >= $\200, C =< $\240 ->
scan1(Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $a, C =< $z -> %Keywords
scan_key_word(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
+scan1([C|Cs], Toks, Pos) when C >= $ß, C =< $ÿ, C /= $÷ ->
scan_key_word(C, Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $A, C =< $Z -> %Variables
scan_variable(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
+scan1([C|Cs], Toks, Pos) when C >= $À, C =< $Þ, C /= $× ->
scan_variable(C, Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Numbers
scan_number(C, Cs, Toks, Pos);
@@ -335,9 +336,9 @@ scan_name([], Ncs) ->
{Ncs,[]}.
name_char(C) when C >= $a, C =< $z -> true;
-name_char(C) when C >= $�, C =< $�, C /= $� -> true;
+name_char(C) when C >= $ß, C =< $ÿ, C /= $÷ -> true;
name_char(C) when C >= $A, C =< $Z -> true;
-name_char(C) when C >= $�, C =< $�, C /= $� -> true;
+name_char(C) when C >= $À, C =< $Þ, C /= $× -> true;
name_char(C) when C >= $0, C =< $9 -> true;
name_char($_) -> true;
name_char($@) -> true;
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl
index 2f0ada122e..4335d8efae 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_check.erl
@@ -4599,7 +4599,7 @@ get_simple_table_info1(S,#'ComponentType'{typespec=TS},[],Path) ->
%% o.w. the asn1 code is wrong.
#type{def=OCFT,constraint=Cnstr} = TS,
case Cnstr of
- [{simpletable,_OSRef}]�->
+ [{simpletable,_OSRef}] ->
#'ObjectClassFieldType'{classname=ClRef,
class=ObjectClass,
fieldname=FieldName} = OCFT,
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl
index 5d2f7a13bd..32d4a22645 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl
@@ -148,7 +148,7 @@ pgen_partial_inc_dec(Erules,Module) ->
% io:format("Start partial incomplete decode gen?~n"),
case asn1ct:get_gen_state_field(inc_type_pattern) of
undefined ->
-% io:format("Partial incomplete decode gen not started:�~w~n",[asn1ct:get_gen_state_field(active)]),
+% io:format("Partial incomplete decode gen not started: ~w~n",[asn1ct:get_gen_state_field(active)]),
ok;
% [] ->
% ok;
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl
index 6064515a7e..b0786200fc 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin.erl
@@ -276,7 +276,7 @@ encode_tag_val({Class, Form, TagNo}) ->
<<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>;
%% asumes whole correct tag bitpattern, multiple of 8
-encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% anv�nds denna funktion??!!
+encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% is this function used??!!
%% asumes correct bitpattern of 0-5
encode_tag_val(Tag) -> encode_tag_val2(Tag,[]).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl
index 50a91cf201..2f25e35cd3 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_ber_bin_v2.erl
@@ -531,7 +531,7 @@ encode_tag_val({Class, Form, TagNo}) ->
<<(Class bsr 6):2, (Form bsr 5):1, 31:5,BinOct/binary>>;
%% asumes whole correct tag bitpattern, multiple of 8
-encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% anv�nds denna funktion??!!
+encode_tag_val(Tag) when (Tag =< 255) -> Tag; %% is this function used??!!
%% asumes correct bitpattern of 0-5
encode_tag_val(Tag) -> encode_tag_val2(Tag,[]).
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl
index 9f02ad4466..4781c81955 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1rt_per_bin_rt2ct.erl
@@ -1198,7 +1198,7 @@ encode_bin_bit_string(C,UnusedAndBin={_,_},NamedBitList) ->
% case get_constraint(C,'SizeConstraint') of
% 0 ->
-% []; % borde avg�ras i compile-time
+% []; % should be dont in compile time
% V when integer(V),V=<16 ->
% {Unused2,Bin2} = pad_list(V,UnusedAndBin1),
% <<BitVal:V,_:Unused2>> = Bin2,
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl
index 48cc50ae21..5a8f9710d6 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_connection.erl
@@ -1,4 +1,5 @@
-% Copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
+%% -*- coding: utf-8 -*-
+% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
@@ -21,7 +22,7 @@
%%% Created : 18 Apr 2008 by Thorsten Schuett <[email protected]>
%%%-------------------------------------------------------------------
%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
+%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
%% @version $Id $
-module(comm_layer_dir.comm_connection).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl
index e8169b4673..d9fcb5e625 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/comm_layer/comm_port.erl
@@ -1,4 +1,5 @@
-% Copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
+%% -*- coding: utf-8 -*-
+% Copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
@@ -20,7 +21,7 @@
%%% Created : 18 Apr 2008 by Thorsten Schuett <[email protected]>
%%%-------------------------------------------------------------------
%% @author Thorsten Schuett <[email protected]>
-%% @copyright 2008 Konrad-Zuse-Zentrum f�r Informationstechnik Berlin
+%% @copyright 2008 Konrad-Zuse-Zentrum für Informationstechnik Berlin
%% @version $Id $
-module(comm_layer_dir.comm_port).
diff --git a/lib/edoc/priv/edoc.dtd b/lib/edoc/priv/edoc.dtd
index 6a332cf22f..ba4ac0db28 100644
--- a/lib/edoc/priv/edoc.dtd
+++ b/lib/edoc/priv/edoc.dtd
@@ -4,7 +4,8 @@
<!ELEMENT overview (title, description?, author*, copyright?, version?,
since?, see*, reference*, todo?, packages, modules)>
<!ATTLIST overview
- root CDATA #IMPLIED>
+ root CDATA #IMPLIED
+ encoding CDATA #IMPLIED>
<!ELEMENT title (#PCDATA)>
@@ -25,6 +26,7 @@
name CDATA #REQUIRED
private (yes | no) #IMPLIED
hidden (yes | no) #IMPLIED
+ encoding CDATA #IMPLIED
root CDATA #IMPLIED>
<!ELEMENT description (briefDescription, fullDescription?)>
diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl
index 544465b14a..599036f380 100644
--- a/lib/edoc/src/edoc.erl
+++ b/lib/edoc/src/edoc.erl
@@ -120,7 +120,8 @@ file(Name, Options) ->
Suffix = proplists:get_value(file_suffix, Options,
?DEFAULT_FILE_SUFFIX),
Dir = proplists:get_value(dir, Options, filename:dirname(Name)),
- edoc_lib:write_file(Text, Dir, BaseName ++ Suffix).
+ Encoding = [{encoding, edoc_lib:read_encoding(Name, [])}],
+ edoc_lib:write_file(Text, Dir, BaseName ++ Suffix, '', Encoding).
%% TODO: better documentation of files/1/2, packages/1/2, application/1/2/3
@@ -455,14 +456,14 @@ expand_sources(Ss, Opts) ->
end,
expand_sources(Ss1, Suffix, sets:new(), [], []).
-expand_sources([{P, F, D} | Fs], Suffix, S, As, Ms) ->
- M = list_to_atom(packages:concat(P, filename:rootname(F, Suffix))),
+expand_sources([{'', F, D} | Fs], Suffix, S, As, Ms) ->
+ M = list_to_atom(filename:rootname(F, Suffix)),
case sets:is_element(M, S) of
true ->
expand_sources(Fs, Suffix, S, As, Ms);
false ->
S1 = sets:add_element(M, S),
- expand_sources(Fs, Suffix, S1, [{M, P, F, D} | As],
+ expand_sources(Fs, Suffix, S1, [{M, '', F, D} | As],
[M | Ms])
end;
expand_sources([], _Suffix, _S, As, Ms) ->
diff --git a/lib/edoc/src/edoc.hrl b/lib/edoc/src/edoc.hrl
index 98debba4ab..44c5d6fef4 100644
--- a/lib/edoc/src/edoc.hrl
+++ b/lib/edoc/src/edoc.hrl
@@ -48,7 +48,8 @@
%% functions = ordset(function_name()),
%% exports = ordset(function_name()),
%% attributes = ordset({atom(), term()}),
-%% records = [{atom(), [{atom(), term()}]}]}
+%% records = [{atom(), [{atom(), term()}]}],
+%% encoding = epp:source_encoding()}
%% ordset(T) = sets:ordset(T)
%% function_name(T) = {atom(), integer()}
@@ -57,7 +58,8 @@
functions = [],
exports = [],
attributes = [],
- records = []
+ records = [],
+ encoding = latin1
}).
%% Environment for generating documentation data
diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl
index 624f9177a2..f88ba05f4b 100644
--- a/lib/edoc/src/edoc_data.erl
+++ b/lib/edoc/src/edoc_data.erl
@@ -83,7 +83,8 @@ module(Module, Entries, Env, Opts) ->
AllTags = get_all_tags(Entries),
Functions = function_filter(Entries, Opts),
Out = {module, ([{name, Name},
- {root, Env#env.root}]
+ {root, Env#env.root},
+ {encoding, Module#module.encoding}]
++ case is_private(HeaderTags) of
true -> [{private, "yes"}];
false -> []
diff --git a/lib/edoc/src/edoc_doclet.erl b/lib/edoc/src/edoc_doclet.erl
index 385d20e9ae..a0c1ae1c0f 100644
--- a/lib/edoc/src/edoc_doclet.erl
+++ b/lib/edoc/src/edoc_doclet.erl
@@ -192,8 +192,9 @@ source({M, P, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden,
andalso ((not is_hidden(Doc)) orelse Hidden) of
true ->
Text = edoc:layout(Doc, Options),
- Name1 = packages:last(M) ++ Suffix,
- edoc_lib:write_file(Text, Dir, Name1, P),
+ Name1 = atom_to_list(M) ++ Suffix,
+ Encoding = [{encoding,encoding(Doc)}],
+ edoc_lib:write_file(Text, Dir, Name1, P, Encoding),
{sets:add_element(Module, Set), Error};
false ->
{Set, Error}
@@ -204,9 +205,9 @@ source({M, P, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden,
end.
check_name(M, M0, P0, File) ->
- P = list_to_atom(packages:strip_last(M)),
- N = packages:last(M),
- N0 = packages:last(M0),
+ P = '',
+ N = M,
+ N0 = M0,
case N of
[$? | _] ->
%% A module name of the form '?...' is assumed to be caused
@@ -359,14 +360,19 @@ xhtml_1(Title, CSS, Body) ->
overview(Dir, Title, Env, Opts) ->
File = proplists:get_value(overview, Opts,
filename:join(Dir, ?OVERVIEW_FILE)),
+ Encoding = edoc_lib:read_encoding(File, [{in_comment_only, false}]),
Tags = read_file(File, overview, Env, Opts),
- Data = edoc_data:overview(Title, Tags, Env, Opts),
+ Data0 = edoc_data:overview(Title, Tags, Env, Opts),
+ EncodingAttribute = #xmlAttribute{name = encoding,
+ value = atom_to_list(Encoding)},
+ #xmlElement{attributes = As} = Data0,
+ Data = Data0#xmlElement{attributes = [EncodingAttribute | As]},
F = fun (M) ->
M:overview(Data, Opts)
end,
Text = edoc_lib:run_layout(F, Opts),
- edoc_lib:write_file(Text, Dir, ?OVERVIEW_SUMMARY).
-
+ EncOpts = [{encoding,Encoding}],
+ edoc_lib:write_file(Text, Dir, ?OVERVIEW_SUMMARY, '', EncOpts).
copy_image(Dir) ->
case code:priv_dir(?EDOC_APP) of
@@ -441,6 +447,12 @@ is_hidden(E) ->
_ -> false
end.
+encoding(E) ->
+ case get_attrval(encoding, E) of
+ "latin1" -> latin1;
+ _ -> utf8
+ end.
+
get_attrval(Name, #xmlElement{attributes = As}) ->
case get_attr(Name, As) of
[#xmlAttribute{value = V}] ->
diff --git a/lib/edoc/src/edoc_extract.erl b/lib/edoc/src/edoc_extract.erl
index 5a79e127f6..67a95e80aa 100644
--- a/lib/edoc/src/edoc_extract.erl
+++ b/lib/edoc/src/edoc_extract.erl
@@ -121,7 +121,7 @@ source1(Tree, File0, Env, Opts, TypeDocs) ->
Module = get_module_info(Tree, File),
{Header, Footer, Entries} = collect(Forms, Module),
Name = Module#module.name,
- Package = list_to_atom(packages:strip_last(Name)),
+ Package = '',
Env1 = Env#env{module = Name,
package = Package,
root = edoc_refs:relative_package_path('', Package)},
@@ -226,7 +226,7 @@ add_macro_defs(Defs0, Opts, Env) ->
%% lines of text before the first tag are ignored. `Env' is an
%% environment created by {@link edoc_lib:get_doc_env/4}. Upon error,
%% `Reason' is an atom returned from the call to {@link
-%% //kernel/file:read_file/1}.
+%% //kernel/file:read_file/1} or the atom 'invalid_unicode'.
%%
%% See {@link text/4} for options.
@@ -235,7 +235,13 @@ add_macro_defs(Defs0, Opts, Env) ->
file(File, Context, Env, Opts) ->
case file:read_file(File) of
{ok, Bin} ->
- {ok, text(binary_to_list(Bin), Context, Env, Opts, File)};
+ Enc = edoc_lib:read_encoding(File,[{in_comment_only, false}]),
+ case catch unicode:characters_to_list(Bin, Enc) of
+ String when is_list(String) ->
+ {ok, text(String, Context, Env, Opts, File)};
+ _ ->
+ {error, invalid_unicode}
+ end;
{error, _} = Error ->
Error
end.
@@ -306,12 +312,14 @@ get_module_info(Forms, File) ->
Exports = ordsets:from_list(get_list_keyval(exports, L)),
Attributes = ordsets:from_list(get_list_keyval(attributes, L)),
Records = get_list_keyval(records, L),
+ Encoding = edoc_lib:read_encoding(File, []),
#module{name = Name,
parameters = Vars,
functions = Functions,
exports = ordsets:intersection(Exports, Functions),
attributes = Attributes,
- records = Records}.
+ records = Records,
+ encoding = Encoding}.
get_list_keyval(Key, L) ->
case lists:keyfind(Key, 1, L) of
diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl
index 951cec121c..7bd0615f5c 100644
--- a/lib/edoc/src/edoc_layout.erl
+++ b/lib/edoc/src/edoc_layout.erl
@@ -210,7 +210,8 @@ layout_module(#xmlElement{name = module, content = Es}=E, Opts) ->
++ [hr, ?NL]
++ navigation("bottom")
++ timestamp()),
- xhtml(Title, stylesheet(Opts), Body).
+ Encoding = get_attrval(encoding, E),
+ xhtml(Title, stylesheet(Opts), Body, Encoding).
module_params(Es) ->
As = [{get_text(argName, Es1),
@@ -956,10 +957,17 @@ local_label(R) ->
"#" ++ R.
xhtml(Title, CSS, Body) ->
+ xhtml(Title, CSS, Body, "latin1").
+
+xhtml(Title, CSS, Body, Encoding) ->
+ EncString = case Encoding of
+ "latin1" -> "ISO-8859-1";
+ _ -> "UTF-8"
+ end,
[{html, [?NL,
{head, [?NL,
{meta, [{'http-equiv',"Content-Type"},
- {content, "text/html; charset=ISO-8859-1"}],
+ {content, "text/html; charset="++EncString}],
[]},
?NL,
{title, Title},
@@ -1021,7 +1029,8 @@ overview(E=#xmlElement{name = overview, content = Es}, Options) ->
++ [?NL, hr]
++ navigation("bottom")
++ timestamp()),
- XML = xhtml(Title, stylesheet(Opts), Body),
+ Encoding = get_attrval(encoding, E),
+ XML = xhtml(Title, stylesheet(Opts), Body, Encoding),
xmerl:export_simple(XML, ?HTML_EXPORT, []).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% NYTT
diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl
index 90fb8a679c..3d193c4bfa 100644
--- a/lib/edoc/src/edoc_lib.erl
+++ b/lib/edoc/src/edoc_lib.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%% =====================================================================
%% This library is free software; you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as
@@ -30,10 +31,10 @@
parse_contact/2, escape_uri/1, join_uri/2, is_relative_uri/1,
is_name/1, to_label/1, find_doc_dirs/0, find_sources/2,
find_sources/3, find_file/3, try_subdir/2, unique/1,
- write_file/3, write_file/4, write_info_file/4,
+ write_file/3, write_file/4, write_file/5, write_info_file/4,
read_info_file/1, get_doc_env/1, get_doc_env/4, copy_file/2,
uri_get/1, run_doclet/2, run_layout/2,
- simplify_path/1, timestr/1, datestr/1]).
+ simplify_path/1, timestr/1, datestr/1, read_encoding/2]).
-import(edoc_report, [report/2, warning/2]).
@@ -57,6 +58,13 @@ datestr({Y,M,D}) ->
lists:flatten(io_lib:fwrite("~s ~w ~w",[lists:nth(M, Ms),D,Y])).
%% @private
+read_encoding(File, Options) ->
+ case epp:read_encoding(File, Options) of
+ none -> epp:default_encoding();
+ Encoding -> Encoding
+ end.
+
+%% @private
count(X, Xs) ->
count(X, Xs, 0).
@@ -228,13 +236,13 @@ end_of_sentence_1(_, false, _) ->
%% 173 - 176 { - ~ punctuation
%% 177 DEL control
%% 200 - 237 control
-%% 240 - 277 NBSP - � punctuation
-%% 300 - 326 � - � uppercase
-%% 327 � punctuation
-%% 330 - 336 � - � uppercase
-%% 337 - 366 � - � lowercase
-%% 367 � punctuation
-%% 370 - 377 � - � lowercase
+%% 240 - 277 NBSP - ¿ punctuation
+%% 300 - 326 À - Ö uppercase
+%% 327 × punctuation
+%% 330 - 336 Ø - Þ uppercase
+%% 337 - 366 ß - ö lowercase
+%% 367 ÷ punctuation
+%% 370 - 377 ø - ÿ lowercase
%% Names must begin with a lowercase letter and contain only
%% alphanumerics and underscores.
@@ -261,6 +269,10 @@ is_name_1(_) -> false.
to_atom(A) when is_atom(A) -> A;
to_atom(S) when is_list(S) -> list_to_atom(S).
+
+to_list(A) when is_atom(A) -> atom_to_list(A);
+to_list(S) when is_list(S) -> S.
+
%% @private
unique([X | Xs]) -> [X | unique(Xs, X)];
@@ -677,7 +689,6 @@ try_subdir(Dir, Subdir) ->
write_file(Text, Dir, Name) ->
write_file(Text, Dir, Name, '').
-
%% @spec (Text::deep_string(), Dir::edoc:filename(),
%% Name::edoc:filename(), Package::atom()|string()) -> ok
%% @doc Like {@link write_file/3}, but adds path components to the target
@@ -685,10 +696,12 @@ write_file(Text, Dir, Name) ->
%% @private
write_file(Text, Dir, Name, Package) ->
- Dir1 = filename:join([Dir | packages:split(Package)]),
- File = filename:join(Dir1, Name),
+ write_file(Text, Dir, Name, Package, [{encoding,latin1}]).
+
+write_file(Text, Dir, Name, Package, Options) ->
+ File = filename:join([Dir, to_list(Package), Name]),
ok = filelib:ensure_dir(File),
- case file:open(File, [write]) of
+ case file:open(File, [write] ++ Options) of
{ok, FD} ->
io:put_chars(FD, Text),
ok = file:close(FD);
@@ -705,8 +718,9 @@ write_info_file(App, Packages, Modules, Dir) ->
Ts1 = if App =:= ?NO_APP -> Ts;
true -> [{application, App} | Ts]
end,
- S = [io_lib:fwrite("~p.\n", [T]) || T <- Ts1],
- write_file(S, Dir, ?INFO_FILE).
+ S0 = [io_lib:fwrite("~p.\n", [T]) || T <- Ts1],
+ S = ["%% encoding: UTF-8\n" | S0],
+ write_file(S, Dir, ?INFO_FILE, '', [{encoding,unicode}]).
%% @spec (Name::edoc:filename()) -> {ok, string()} | {error, Reason}
%%
@@ -714,7 +728,14 @@ write_info_file(App, Packages, Modules, Dir) ->
read_file(File) ->
case file:read_file(File) of
- {ok, Bin} -> {ok, binary_to_list(Bin)};
+ {ok, Bin} ->
+ Enc = edoc_lib:read_encoding(File, []),
+ case catch unicode:characters_to_list(Bin, Enc) of
+ String when is_list(String) ->
+ {ok, String};
+ _ ->
+ {error, invalid_unicode}
+ end;
{error, Reason} -> {error, Reason}
end.
@@ -818,7 +839,7 @@ find_sources(Path, Pkg, Rec, Ext, Opts) ->
lists:flatten(find_sources_1(Path, to_atom(Pkg), Rec, Ext, Skip)).
find_sources_1([P | Ps], Pkg, Rec, Ext, Skip) ->
- Dir = filename:join(P, filename:join(packages:split(Pkg))),
+ Dir = filename:join(P, atom_to_list(Pkg)),
Fs1 = find_sources_1(Ps, Pkg, Rec, Ext, Skip),
case filelib:is_dir(Dir) of
true ->
@@ -844,9 +865,9 @@ find_sources_2(Dir, Pkg, Rec, Ext, Skip) ->
[]
end.
-find_sources_3(Es, Dir, Pkg, Rec, Ext, Skip) ->
+find_sources_3(Es, Dir, '', Rec, Ext, Skip) ->
[find_sources_2(filename:join(Dir, E),
- to_atom(packages:concat(Pkg, E)), Rec, Ext, Skip)
+ to_atom(E), Rec, Ext, Skip)
|| E <- Es, is_package_dir(E, Dir)].
is_source_file(Name, Ext) ->
@@ -858,16 +879,16 @@ is_package_dir(Name, Dir) ->
andalso filelib:is_dir(filename:join(Dir, Name)).
%% @private
-find_file([P | Ps], Pkg, Name) ->
- Dir = filename:join(P, filename:join(packages:split(Pkg))),
- File = filename:join(Dir, Name),
+find_file([P | Ps], []=Pkg, Name) ->
+ Pkg = [],
+ File = filename:join(P, Name),
case filelib:is_file(File) of
true ->
File;
false ->
find_file(Ps, Pkg, Name)
end;
-find_file([], _Pkg, _Name) ->
+find_file([], [], _Name) ->
"".
%% @private
diff --git a/lib/edoc/src/edoc_macros.erl b/lib/edoc/src/edoc_macros.erl
index 70fb38bf0a..08686c4fb5 100644
--- a/lib/edoc/src/edoc_macros.erl
+++ b/lib/edoc/src/edoc_macros.erl
@@ -88,13 +88,13 @@ link_macro(S, Line, Env) ->
true -> " target=\"_top\""; % note the initial space
false -> ""
end,
- lists:flatten(io_lib:fwrite("<a href=\"~s\"~s>~s</a>",
+ lists:flatten(io_lib:fwrite("<a href=\"~s\"~s>~ts</a>",
[URI, Target, Txt])).
section_macro(S, _Line, _Env) ->
S1 = lists:reverse(edoc_lib:strip_space(
lists:reverse(edoc_lib:strip_space(S)))),
- lists:flatten(io_lib:format("<a href=\"#~s\">~s</a>",
+ lists:flatten(io_lib:format("<a href=\"#~ts\">~ts</a>",
[edoc_lib:to_label(S1), S1])).
type_macro(S, Line, Env) ->
diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl
index d7c1b1c045..cf1a2d6b11 100644
--- a/lib/edoc/src/edoc_parser.yrl
+++ b/lib/edoc/src/edoc_parser.yrl
@@ -1,6 +1,7 @@
+%% -*- coding: utf-8 -*-
%% ========================== -*-Erlang-*- =============================
%% EDoc type specification grammar for the Yecc parser generator,
-%% adapted from Sven-Olof Nystr�m's type specification parser.
+%% adapted from Sven-Olof Nyström's type specification parser.
%%
%% Also contains entry points for parsing things like typedefs,
%% references, and throws-declarations.
@@ -317,10 +318,7 @@ tok_val(T) -> element(3, T).
tok_line(T) -> element(2, T).
-qname([A]) ->
- A; % avoid unnecessary call to packages:concat/1.
-qname(List) ->
- list_to_atom(packages:concat(lists:reverse(List))).
+qname([A]) -> A.
union(Ts) ->
case Ts of
diff --git a/lib/edoc/src/edoc_refs.erl b/lib/edoc/src/edoc_refs.erl
index 1f578a3b83..ea439490ed 100644
--- a/lib/edoc/src/edoc_refs.erl
+++ b/lib/edoc/src/edoc_refs.erl
@@ -126,7 +126,7 @@ abs_uri({package, P}, Env) ->
module_ref(M, Env) ->
case (Env#env.modules)(M) of
"" ->
- File = packages:last(M) ++ Env#env.file_suffix,
+ File = atom_to_list(M) ++ Env#env.file_suffix,
Path = relative_module_path(M, Env#env.package),
join_uri(Path, escape_uri(File));
Base ->
@@ -134,8 +134,7 @@ module_ref(M, Env) ->
end.
module_absref(M, Env) ->
- join_segments(packages:split(M))
- ++ escape_uri(Env#env.file_suffix).
+ escape_uri(atom_to_list(M)) ++ escape_uri(Env#env.file_suffix).
package_ref(P, Env) ->
case (Env#env.packages)(P) of
@@ -147,7 +146,7 @@ package_ref(P, Env) ->
end.
package_absref(P, Env) ->
- join_uri(join_segments(packages:split(P)),
+ join_uri(escape_uri(atom_to_list(P)),
escape_uri(Env#env.package_summary)).
app_ref(A, Env) ->
@@ -179,14 +178,11 @@ join_segments([S | Ss]) ->
%% The empty string is returned if the To module has only one segment,
%% implying a local reference.
-relative_module_path(To, From) ->
- case first(packages:split(To)) of
- [] -> "";
- P -> relative_path(P, packages:split(From))
- end.
+relative_module_path(_To, _From) ->
+ "".
relative_package_path(To, From) ->
- relative_path(packages:split(To), packages:split(From)).
+ relative_path([atom_to_list(To)], [atom_to_list(From)]).
%% This takes two lists of path segments (From, To). Note that an empty
%% string will be returned if the paths are the same. Empty leading
@@ -210,6 +206,3 @@ relative_path_2([], []) ->
"";
relative_path_2([], Ts) ->
join_segments(Ts).
-
-first([H | T]) when T /= [] -> [H | first(T)];
-first(_) -> [].
diff --git a/lib/edoc/src/edoc_wiki.erl b/lib/edoc/src/edoc_wiki.erl
index 5c71658af5..cc0529d2a9 100644
--- a/lib/edoc/src/edoc_wiki.erl
+++ b/lib/edoc/src/edoc_wiki.erl
@@ -80,6 +80,7 @@ parse_xml(Data, Line) ->
parse_xml_1(Text, Line) ->
Text1 = "<doc>" ++ Text ++ "</doc>",
+ %% Any coding except "utf-8".
Opts = [{line, Line}, {encoding, 'iso-8859-1'}],
case catch {ok, xmerl_scan:string(Text1, Opts)} of
{ok, {E, _}} ->
@@ -174,7 +175,7 @@ expand_heading_1(Cs, N, L, As) ->
expand_heading_2(Ts, Cs, N, L, As) ->
H = ?BASE_HEADING + N,
- Ts1 = io_lib:format("<h~w><a name=\"~s\">~s</a></h~w>\n",
+ Ts1 = io_lib:format("<h~w><a name=\"~ts\">~ts</a></h~w>\n",
[H, make_label(Ts), Ts, H]),
expand_new_line(Cs, L + 1, lists:reverse(lists:flatten(Ts1), As)).
diff --git a/lib/erl_docgen/doc/src/doc-build.xml b/lib/erl_docgen/doc/src/doc-build.xml
index 08410a1539..ae1b17dff5 100644
--- a/lib/erl_docgen/doc/src/doc-build.xml
+++ b/lib/erl_docgen/doc/src/doc-build.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2011</year>
+ <year>1997</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -56,7 +56,8 @@
</p>
<code>
- 1> escript $(ERL_TOP)/lib/erl_docgen/priv/bin/codeline_preprocessing.escript ex1.xmlsrc ex1.xml
+ 1> escript $(ERL_TOP)/lib/erl_docgen/priv/bin/codeline_preprocessing.escript \
+ ex1.xmlsrc ex1.xml
</code>
</section>
</section>
diff --git a/lib/erl_docgen/priv/bin/xml_from_edoc.escript b/lib/erl_docgen/priv/bin/xml_from_edoc.escript
index 2cb81be1be..65a580dca2 100755
--- a/lib/erl_docgen/priv/bin/xml_from_edoc.escript
+++ b/lib/erl_docgen/priv/bin/xml_from_edoc.escript
@@ -2,7 +2,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -100,10 +100,12 @@ module(File, Args) ->
users_guide(File, Args) ->
case filelib:is_regular(File) of
true ->
+ Enc = epp:read_encoding(File, [{in_comment_only, false}]),
+ Encoding = [{encoding, Enc} || Enc =/= none],
Opts = [{def, Args#args.def},
{app_default, "OTPROOT"},
{file_suffix, Args#args.suffix},
- {layout, Args#args.layout}],
+ {layout, Args#args.layout}] ++ Encoding,
Env = edoc_lib:get_doc_env(Opts),
@@ -115,7 +117,7 @@ users_guide(File, Args) ->
Text = edoc_lib:run_layout(F, Opts),
OutFile = "chapter" ++ Args#args.suffix,
- edoc_lib:write_file(Text, ".", OutFile);
+ edoc_lib:write_file(Text, ".", OutFile, '', Encoding);
false ->
io:format("~s: not a regular file\n", [File]),
usage()
diff --git a/lib/erl_docgen/priv/fop.xconf b/lib/erl_docgen/priv/fop.xconf
new file mode 100644
index 0000000000..70ecd608c3
--- /dev/null
+++ b/lib/erl_docgen/priv/fop.xconf
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!--
+ #
+ # %CopyrightBegin%
+ #
+ # Copyright Ericsson AB 2009-2012. All Rights Reserved.
+ #
+ # The contents of this file are subject to the Erlang Public License,
+ # Version 1.1, (the "License"); you may not use this file except in
+ # compliance with the License. You should have received a copy of the
+ # Erlang Public License along with this software. If not, it can be
+ # retrieved online at http://www.erlang.org/.
+ #
+ # Software distributed under the License is distributed on an "AS IS"
+ # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ # the License for the specific language governing rights and limitations
+ # under the License.
+ #
+ # %CopyrightEnd%
+
+ -->
+<!-- NOTE: This is the version of the configuration -->
+<fop version="1.0">
+ <!-- The substitutions of DejaVu 700 are there because FOP outputs
+ warnings about doing the substitutions otherwise -->
+ <fonts>
+ <substitutions>
+ <substitution>
+ <from font-family="DejaVuSans" font-weight="700"/>
+ <to font-family="DejaVuSans" font-weight="400"/>
+ </substitution>
+ <substitution>
+ <from font-family="DejaVuSansMono" font-weight="700"/>
+ <to font-family="DejaVuSansMono" font-weight="400"/>
+ </substitution>
+ </substitutions>
+ </fonts>
+ <renderers>
+ <renderer mime="application/pdf">
+ <fonts>
+ <auto-detect/>
+ </fonts>
+ </renderer>
+ </renderers>
+</fop>
diff --git a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
index 4e61f1f476..2e3b22acf4 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -52,7 +52,7 @@
<!-- XSL-FO properties -->
<xsl:attribute-set name="caption">
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">0.8em</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="keep-with-previous.within-page">always</xsl:attribute>
@@ -61,7 +61,7 @@
</xsl:attribute-set>
<xsl:attribute-set name="pre">
- <xsl:attribute name="font-family">monospace</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSansMono, monospace</xsl:attribute>
<xsl:attribute name="font-size">0.8em</xsl:attribute>
<xsl:attribute name="keep-together.within-page">auto</xsl:attribute>
<xsl:attribute name="linefeed-treatment">preserve</xsl:attribute>
@@ -162,7 +162,7 @@
<xsl:attribute name="border-after-width">1pt</xsl:attribute>
<xsl:attribute name="border-color"><xsl:value-of select="$pdfcolor"/></xsl:attribute>
<xsl:attribute name="break-before">page</xsl:attribute>
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">1.83em</xsl:attribute>
<xsl:attribute name="font-weight">normal</xsl:attribute>
<xsl:attribute name="space-after">1em</xsl:attribute>
@@ -171,7 +171,7 @@
</xsl:attribute-set>
<xsl:attribute-set name="h2">
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">1.5em</xsl:attribute>
<xsl:attribute name="font-weight">normal</xsl:attribute>
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
@@ -180,7 +180,7 @@
</xsl:attribute-set>
<xsl:attribute-set name="h3">
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">1.33em</xsl:attribute>
<xsl:attribute name="font-weight">normal</xsl:attribute>
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
@@ -189,7 +189,7 @@
</xsl:attribute-set>
<xsl:attribute-set name="h4">
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">1.17em</xsl:attribute>
<xsl:attribute name="font-weight">normal</xsl:attribute>
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
@@ -198,7 +198,7 @@
</xsl:attribute-set>
<xsl:attribute-set name="h5">
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">1em</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
@@ -207,7 +207,7 @@
</xsl:attribute-set>
<xsl:attribute-set name="h6">
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">0.83em</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
@@ -227,20 +227,20 @@
<xsl:attribute name="border-after-style">solid</xsl:attribute>
<xsl:attribute name="border-after-width">2pt</xsl:attribute>
<xsl:attribute name="border-color"><xsl:value-of select="$pdfcolor"/></xsl:attribute>
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">0.9em</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="page-footer">
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">0.9em</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="code">
<xsl:attribute name="background-color">#e0e0ff</xsl:attribute>
- <xsl:attribute name="font-family">monospace</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSansMono, monospace</xsl:attribute>
<xsl:attribute name="font-size">0.8em</xsl:attribute>
<xsl:attribute name="keep-together.within-page">auto</xsl:attribute>
<xsl:attribute name="linefeed-treatment">preserve</xsl:attribute>
@@ -303,7 +303,7 @@
<xsl:attribute-set name="module-name">
<xsl:attribute name="border-after-style">solid</xsl:attribute>
<xsl:attribute name="border-after-width">1pt</xsl:attribute>
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">1.5em</xsl:attribute>
<xsl:attribute name="font-weight">normal</xsl:attribute>
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
@@ -313,7 +313,7 @@
<xsl:attribute-set name="function-name">
<xsl:attribute name="font-weight">bold</xsl:attribute>
- <xsl:attribute name="font-family">monospace</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSansMono, monospace</xsl:attribute>
<!-- xsl:attribute name="font-size">0.8em</xsl:attribute -->
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
<xsl:attribute name="space-after">0.25em</xsl:attribute>
@@ -401,7 +401,7 @@
</xsl:attribute-set>
<xsl:attribute-set name="caption">
- <xsl:attribute name="font-family">sans-serif</xsl:attribute>
+ <xsl:attribute name="font-family">DejaVuSans, sans-serif</xsl:attribute>
<xsl:attribute name="font-size">0.8em</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="keep-with-previous.within-page">always</xsl:attribute>
diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
index cbaa93a15d..e3cc354206 100644
--- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
+++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
@@ -1,19 +1,20 @@
-%% ``The contents of this file are subject to the Erlang Public License,
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
+%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See
-%% the Licence for the specific language governing rights and limitations
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
%% under the License.
%%
-%% The Initial Developer of the Original Code is Ericsson AB.
-%% Portions created by Ericsson are Copyright 1999-2006, Ericsson AB.
-%% All Rights Reserved.��
-%%
-%% $Id$
+%% %CopyrightEnd%
%%
-module(docgen_edoc_xml_cb).
@@ -39,12 +40,14 @@
module(Element, Opts) ->
SortP = proplists:get_value(sort_functions, Opts, true),
XML = layout_module(Element, SortP),
- xmerl:export_simple([XML], docgen_xmerl_xml_cb, []).
+ RootAttributes = root_attributes(Element, Opts),
+ xmerl:export_simple([XML], docgen_xmerl_xml_cb, RootAttributes).
%% CHAPTER
-overview(Element, _Opts) ->
+overview(Element, Opts) ->
XML = layout_chapter(Element),
- xmerl:export_simple([XML], docgen_xmerl_xml_cb, []).
+ RootAttributes = root_attributes(Element, Opts),
+ xmerl:export_simple([XML], docgen_xmerl_xml_cb, RootAttributes).
%%--Internal functions--------------------------------------------------
@@ -99,6 +102,16 @@ layout_module(#xmlElement{name = module, content = Es}=E, SortP) ->
?NL,Authors]
}.
+root_attributes(Element, Opts) ->
+ Encoding = case get_attrval(encoding, Element) of
+ "" ->
+ DefaultEncoding = epp:default_encoding(),
+ proplists:get_value(encoding, Opts, DefaultEncoding);
+ Enc ->
+ Enc
+ end,
+ [#xmlAttribute{name=encoding, value=Encoding}].
+
layout_chapter(#xmlElement{name=overview, content=Es}) ->
Title = get_text(title, Es),
Header = {header, [
diff --git a/lib/erl_docgen/src/docgen_xmerl_xml_cb.erl b/lib/erl_docgen/src/docgen_xmerl_xml_cb.erl
index 884932ed12..d713b61c0a 100644
--- a/lib/erl_docgen/src/docgen_xmerl_xml_cb.erl
+++ b/lib/erl_docgen/src/docgen_xmerl_xml_cb.erl
@@ -1,19 +1,20 @@
-%% ``The contents of this file are subject to the Erlang Public License,
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
+%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See
-%% the Licence for the specific language governing rights and limitations
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
%% under the License.
%%
-%% The Initial Developer of the Original Code is Ericsson AB.
-%% Portions created by Ericsson are Copyright 1999-2006, Ericsson AB.
-%% All Rights Reserved.��
-%%
-%% $Id$
+%% %CopyrightEnd%
%%
-module(docgen_xmerl_xml_cb).
@@ -35,9 +36,14 @@
'#xml-inheritance#'() ->
[xmerl_xml].
-'#root#'(Data, _Attrs, [], _E) ->
+'#root#'(Data, Attrs, [], _E) ->
+ Encoding =
+ case [E || #xmlAttribute{name = encoding, value = E} <- Attrs] of
+ [E] -> E;
+ _ -> atom_to_list(epp:default_encoding())
+ end,
["<",DTD,">"] = hd(hd(Data)),
- ["<?xml version=\"1.0\" encoding=\"latin1\" ?>\n",
+ ["<?xml version=\"1.0\" encoding=\"",Encoding,"\" ?>\n",
"<!DOCTYPE "++DTD++" SYSTEM \""++DTD++".dtd\">\n",
Data].
diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl
index bb44b78854..2c4b6e5541 100644
--- a/lib/erl_interface/test/ei_decode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -204,15 +205,15 @@ test_ei_decode_misc(Config) when is_list(Config) ->
?line send_term_as_binary(P,foo),
?line send_term_as_binary(P,''),
- ?line send_term_as_binary(P,'������'),
+ ?line send_term_as_binary(P,'ÅÄÖåäö'),
?line send_term_as_binary(P,"foo"),
?line send_term_as_binary(P,""),
- ?line send_term_as_binary(P,"������"),
+ ?line send_term_as_binary(P,"ÅÄÖåäö"),
?line send_term_as_binary(P,<<"foo">>),
?line send_term_as_binary(P,<<>>),
- ?line send_term_as_binary(P,<<"������">>),
+ ?line send_term_as_binary(P,<<"ÅÄÖåäö">>),
% ?line send_term_as_binary(P,{}),
% ?line send_term_as_binary(P,[]),
diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl
index cefd33e5f6..537e9cb01c 100644
--- a/lib/erl_interface/test/ei_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_encode_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -213,19 +214,19 @@ test_ei_encode_misc(Config) when is_list(Config) ->
?line {<<100,0,3,"foo">>,foo} = get_buf_and_term(P),
?line {<<100,0,0,"">>,''} = get_buf_and_term(P),
?line {<<100,0,0,"">>,''} = get_buf_and_term(P),
- ?line {<<100,0,6,"������">>,'������'} = get_buf_and_term(P),
- ?line {<<100,0,6,"������">>,'������'} = get_buf_and_term(P),
+ ?line {<<100,0,6,"ÅÄÖåäö">>,'ÅÄÖåäö'} = get_buf_and_term(P),
+ ?line {<<100,0,6,"ÅÄÖåäö">>,'ÅÄÖåäö'} = get_buf_and_term(P),
?line {<<107,0,3,"foo">>,"foo"} = get_buf_and_term(P),
?line {<<107,0,3,"foo">>,"foo"} = get_buf_and_term(P),
?line {<<106>>,""} = get_buf_and_term(P),
?line {<<106>>,""} = get_buf_and_term(P),
- ?line {<<107,0,6,"������">>,"������"} = get_buf_and_term(P),
- ?line {<<107,0,6,"������">>,"������"} = get_buf_and_term(P),
+ ?line {<<107,0,6,"ÅÄÖåäö">>,"ÅÄÖåäö"} = get_buf_and_term(P),
+ ?line {<<107,0,6,"ÅÄÖåäö">>,"ÅÄÖåäö"} = get_buf_and_term(P),
?line {<<109,0,0,0,3,"foo">>,<<"foo">>} = get_buf_and_term(P),
?line {<<109,0,0,0,0,"">>,<<>>} = get_buf_and_term(P),
- ?line {<<109,0,0,0,6,"������">>,<<"������">>} = get_buf_and_term(P),
+ ?line {<<109,0,0,0,6,"ÅÄÖåäö">>,<<"ÅÄÖåäö">>} = get_buf_and_term(P),
?line {<<104,0>>,{}} = get_buf_and_term(P), % Tuple header for {}
?line {<<106>>,[]} = get_buf_and_term(P), % Empty list []
diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl
index 2a3ed81f53..6305302e28 100644
--- a/lib/erl_interface/test/ei_print_SUITE.erl
+++ b/lib/erl_interface/test/ei_print_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -136,7 +136,7 @@ lists(Config) when is_list(Config) ->
%% ?line {term, "[{name, 'Madonna'}, {age, 21}, {data, [{addr, "E-street", 42}]}]"} =
%% get_term(P),
- %% kanske regexp i st�llet?
+ %% maybe regexp instead?
?line {term, "[{pi, 3.141500}, {'cos(70)', 0.342020}]"} = get_term(P),
?line {term, "[[pi, 3.141500], ['cos(70)', 0.342020]]"} = get_term(P),
diff --git a/lib/et/src/et.erl b/lib/et/src/et.erl
index e2cd8564c3..c9ba4f6816 100644
--- a/lib/et/src/et.erl
+++ b/lib/et/src/et.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -102,7 +102,7 @@
%% From = actor()
%% To = actor()
%% FromTo = actor()
-%% Label = atom() | string() |�term()
+%% Label = atom() | string() | term()
%% Contents = [{Key, Value}] | term()
%%
%% actor() = term()
diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl
index fba840c3bd..8ebdb6ba16 100644
--- a/lib/eunit/include/eunit.hrl
+++ b/lib/eunit/include/eunit.hrl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%% This library is free software; you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as
%% published by the Free Software Foundation; either version 2 of the
@@ -13,7 +14,7 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% Copyright (C) 2004-2006 Micka�l R�mond, Richard Carlsson
+%% Copyright (C) 2004-2006 Mickaël Rémond, Richard Carlsson
%% Including this file turns on testing and defines TEST, unless NOTEST
%% is defined before the file is included. If both NOTEST and TEST are
@@ -124,8 +125,8 @@
-ifndef(UNDER_EUNIT).
-define(UNDER_EUNIT,
(?MATCHES({current_function,{eunit_proc,_,_}},
- .erlang:process_info(.erlang:group_leader(),
- current_function)))).
+ erlang:process_info(erlang:group_leader(),
+ current_function)))).
-endif.
%% The plain assert macro should be defined to do nothing if this file
@@ -142,14 +143,14 @@
((fun () ->
case (BoolExpr) of
true -> ok;
- __V -> .erlang:error({assertion_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??BoolExpr)},
- {expected, true},
- {value, case __V of false -> __V;
- _ -> {not_a_boolean,__V}
- end}]})
+ __V -> erlang:error({assertion_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??BoolExpr)},
+ {expected, true},
+ {value, case __V of false -> __V;
+ _ -> {not_a_boolean,__V}
+ end}]})
end
end)())).
-endif.
@@ -170,12 +171,12 @@
((fun () ->
case (Expr) of
Guard -> ok;
- __V -> .erlang:error({assertMatch_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern, (??Guard)},
- {value, __V}]})
+ __V -> erlang:error({assertMatch_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern, (??Guard)},
+ {value, __V}]})
end
end)())).
-endif.
@@ -189,12 +190,12 @@
((fun () ->
__V = (Expr),
case __V of
- Guard -> .erlang:error({assertNotMatch_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern, (??Guard)},
- {value, __V}]});
+ Guard -> erlang:error({assertNotMatch_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern, (??Guard)},
+ {value, __V}]});
_ -> ok
end
end)())).
@@ -210,12 +211,12 @@
((fun (__X) ->
case (Expr) of
__X -> ok;
- __V -> .erlang:error({assertEqual_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {expected, __X},
- {value, __V}]})
+ __V -> erlang:error({assertEqual_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {expected, __X},
+ {value, __V}]})
end
end)(Expect))).
-endif.
@@ -228,11 +229,11 @@
-define(assertNotEqual(Unexpected, Expr),
((fun (__X) ->
case (Expr) of
- __X -> .erlang:error({assertNotEqual_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {value, __X}]});
+ __X -> erlang:error({assertNotEqual_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {value, __X}]});
_ -> ok
end
end)(Unexpected))).
@@ -248,7 +249,7 @@
-define(assertException(Class, Term, Expr),
((fun () ->
try (Expr) of
- __V -> .erlang:error({assertException_failed,
+ __V -> erlang:error({assertException_failed,
[{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
@@ -259,16 +260,16 @@
catch
Class:Term -> ok;
__C:__T ->
- .erlang:error({assertException_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern,
- "{ "++(??Class)++" , "++(??Term)
- ++" , [...] }"},
- {unexpected_exception,
- {__C, __T,
- .erlang:get_stacktrace()}}]})
+ erlang:error({assertException_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern,
+ "{ "++(??Class)++" , "++(??Term)
+ ++" , [...] }"},
+ {unexpected_exception,
+ {__C, __T,
+ erlang:get_stacktrace()}}]})
end
end)())).
-endif.
@@ -299,17 +300,17 @@
Class ->
case __T of
Term ->
- .erlang:error({assertNotException_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expression, (??Expr)},
- {pattern,
- "{ "++(??Class)++" , "
- ++(??Term)++" , [...] }"},
- {unexpected_exception,
- {__C, __T,
- .erlang:get_stacktrace()
- }}]});
+ erlang:error({assertNotException_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expression, (??Expr)},
+ {pattern,
+ "{ "++(??Class)++" , "
+ ++(??Term)++" , [...] }"},
+ {unexpected_exception,
+ {__C, __T,
+ erlang:get_stacktrace()
+ }}]});
_ -> ok
end;
_ -> ok
@@ -324,17 +325,17 @@
%% require EUnit to be present at runtime, or at least eunit_lib.)
%% these can be used for simply running commands in a controlled way
--define(_cmd_(Cmd), (.eunit_lib:command(Cmd))).
+-define(_cmd_(Cmd), (eunit_lib:command(Cmd))).
-define(cmdStatus(N, Cmd),
((fun () ->
case ?_cmd_(Cmd) of
{(N), __Out} -> __Out;
- {__N, _} -> .erlang:error({command_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {command, (Cmd)},
- {expected_status,(N)},
- {status,__N}]})
+ {__N, _} -> erlang:error({command_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {command, (Cmd)},
+ {expected_status,(N)},
+ {status,__N}]})
end
end)())).
-define(_cmdStatus(N, Cmd), ?_test(?cmdStatus(N, Cmd))).
@@ -350,12 +351,12 @@
((fun () ->
case ?_cmd_(Cmd) of
{(N), _} -> ok;
- {__N, _} -> .erlang:error({assertCmd_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {command, (Cmd)},
- {expected_status,(N)},
- {status,__N}]})
+ {__N, _} -> erlang:error({assertCmd_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {command, (Cmd)},
+ {expected_status,(N)},
+ {status,__N}]})
end
end)())).
-endif.
@@ -368,12 +369,12 @@
((fun () ->
case ?_cmd_(Cmd) of
{_, (T)} -> ok;
- {_, __T} -> .erlang:error({assertCmdOutput_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {command,(Cmd)},
- {expected_output,(T)},
- {output,__T}]})
+ {_, __T} -> erlang:error({assertCmdOutput_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {command,(Cmd)},
+ {expected_output,(T)},
+ {output,__T}]})
end
end)())).
-endif.
@@ -394,12 +395,12 @@
-else.
-define(debugMsg(S),
(begin
- .io:fwrite(user, <<"~s:~w:~w: ~s\n">>,
- [?FILE, ?LINE, self(), S]),
+ io:fwrite(user, <<"~s:~w:~w: ~s\n">>,
+ [?FILE, ?LINE, self(), S]),
ok
end)).
-define(debugHere, (?debugMsg("<-"))).
--define(debugFmt(S, As), (?debugMsg(.io_lib:format((S), (As))))).
+-define(debugFmt(S, As), (?debugMsg(io_lib:format((S), (As))))).
-define(debugVal(E),
((fun (__V) ->
?debugFmt(<<"~s = ~P">>, [(??E), __V, 15]),
diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl
index 51846d73b3..5763949519 100644
--- a/lib/eunit/src/eunit.erl
+++ b/lib/eunit/src/eunit.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%% This library is free software; you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as
%% published by the Free Software Foundation; either version 2 of the
@@ -13,8 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% @copyright 2004-2009 Micka�l R�mond, Richard Carlsson
-%% @author Micka�l R�mond <[email protected]>
+%% @copyright 2004-2009 Mickaël Rémond, Richard Carlsson
+%% @author Mickaël Rémond <[email protected]>
%% [http://www.process-one.net/]
%% @author Richard Carlsson <[email protected]>
%% @version {@version}, {@date} {@time}
diff --git a/lib/eunit/src/eunit_autoexport.erl b/lib/eunit/src/eunit_autoexport.erl
index 099bcb222e..36ae3b71d7 100644
--- a/lib/eunit/src/eunit_autoexport.erl
+++ b/lib/eunit/src/eunit_autoexport.erl
@@ -80,10 +80,9 @@ rewrite([F | Fs], As, Module, Test) ->
rewrite(Fs, [F | As], Module, Test);
rewrite([], As, Module, Test) ->
{if Test ->
- EUnit = {record_field,0,{atom,0,''},{atom,0,eunit}},
[{function,0,test,0,
[{clause,0,[],[],
- [{call,0,{remote,0,EUnit,{atom,0,test}},
+ [{call,0,{remote,0,{atom,0,eunit},{atom,0,test}},
[{atom,0,Module}]}]}]}
| As];
true ->
@@ -92,9 +91,7 @@ rewrite([], As, Module, Test) ->
Test}.
module_decl(Name, M, Fs, Exports) ->
- Module = if is_atom(Name) -> Name;
- true -> list_to_atom(packages:concat(Name))
- end,
+ Module = Name,
{Fs1, Test} = rewrite(Fs, [], Module, true),
Es = if Test -> [{test,0} | Exports];
true -> Exports
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index ea9e944d7e..809cb7ab7b 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%% This library is free software; you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as
%% published by the Free Software Foundation; either version 2 of the
@@ -13,8 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% @copyright 2004-2007 Micka�l R�mond, Richard Carlsson
-%% @author Micka�l R�mond <[email protected]>
+%% @copyright 2004-2007 Mickaël Rémond, Richard Carlsson
+%% @author Mickaël Rémond <[email protected]>
%% [http://www.process-one.net/]
%% @author Richard Carlsson <[email protected]>
%% @private
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index 46b8c8b503..cc021625d5 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%% This library is free software; you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as
%% published by the Free Software Foundation; either version 2 of the
@@ -13,8 +14,8 @@
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
-%% @author Micka�l R�mond <[email protected]>
-%% @copyright 2009 Micka�l R�mond, Paul Guyot
+%% @author Mickaël Rémond <[email protected]>
+%% @copyright 2009 Mickaël Rémond, Paul Guyot
%% @see eunit
%% @doc Surefire reports for EUnit (Format used by Maven and Atlassian
%% Bamboo for example to integrate test results). Based on initial code
diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl
index 8ecd649532..a7a786ce98 100644
--- a/lib/gs/contribs/mandel/mandel.erl
+++ b/lib/gs/contribs/mandel/mandel.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -34,7 +35,7 @@
%%%-----------------------------------------------------------------
%%% Distributed Mandelbrot program.
%%% Originally written i C++/rpc/lwp/interviews by Klas Eriksson.(1200 lines)
-%%% Rewritten in Erlang by Klas Eriksson and Martin Bj�rklund.
+%%% Rewritten in Erlang by Klas Eriksson and Martin Björklund.
%%%-----------------------------------------------------------------
%% unix>erl -sname foo (all nodes will get the same name)
diff --git a/lib/gs/src/gstk_editor.erl b/lib/gs/src/gstk_editor.erl
index e918d93147..cb422aef95 100644
--- a/lib/gs/src/gstk_editor.erl
+++ b/lib/gs/src/gstk_editor.erl
@@ -90,9 +90,9 @@
%% type
%%
-%.t tag names 2.7 -> red blue (blue �r f�rgen)
-%.t tag add blue 2.1 2.10 tagga text
-%.t tag configure blue -foregr blue skapa tag
+%.t tag names 2.7 -> red blue (blue is the colour)
+%.t tag add blue 2.1 2.10 tag the text
+%.t tag configure blue -foregr blue create tag
% .t index end -> MaxRows.cols
% .t yview moveto (Row-1)/MaxRows
diff --git a/lib/hipe/amd64/hipe_amd64_encode.erl b/lib/hipe/amd64/hipe_amd64_encode.erl
index ee68dfb3b8..cbdab25b25 100644
--- a/lib/hipe/amd64/hipe_amd64_encode.erl
+++ b/lib/hipe/amd64/hipe_amd64_encode.erl
@@ -1,7 +1,7 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%%
%%% The contents of this file are subject to the Erlang Public License,
%%% Version 1.1, (the "License"); you may not use this file except in
@@ -373,16 +373,16 @@ sse2_arith_binop_encode(Prefix, Opcode, {{xmm, XMM64}, {rm64fp, RM64}}) ->
[Prefix, 16#0F, Opcode | encode_rm(RM64, XMM64, [])].
sse2_cvtsi2sd_encode({{xmm,XMM64}, {rm64,RM64}}) ->
- [rex([{w, 1}]), 16#F2, 16#0F, 16#2A�| encode_rm(RM64, XMM64, [])].
+ [rex([{w, 1}]), 16#F2, 16#0F, 16#2A | encode_rm(RM64, XMM64, [])].
sse2_mov_encode(Opnds) ->
case Opnds of
{{xmm, XMM64}, {rm64fp, RM64}} -> % movsd
- [16#F2, 16#0F, 16#10�| encode_rm(RM64, XMM64, [])];
+ [16#F2, 16#0F, 16#10 | encode_rm(RM64, XMM64, [])];
{{rm64fp, RM64}, {xmm, XMM64}} -> % movsd
- [16#F2, 16#0F, 16#11�| encode_rm(RM64, XMM64, [])]
+ [16#F2, 16#0F, 16#11 | encode_rm(RM64, XMM64, [])]
% {{xmm, XMM64}, {rm64, RM64}} -> % cvtsi2sd
-% [rex([{w, 1}]), 16#F2, 16#0F, 16#2A�| encode_rm(RM64, XMM64, [])]
+% [rex([{w, 1}]), 16#F2, 16#0F, 16#2A | encode_rm(RM64, XMM64, [])]
end.
%% arith_binop_sizeof(Opnds) ->
diff --git a/lib/hipe/flow/hipe_dominators.erl b/lib/hipe/flow/hipe_dominators.erl
index 17357461a5..1f2c830eaf 100644
--- a/lib/hipe/flow/hipe_dominators.erl
+++ b/lib/hipe/flow/hipe_dominators.erl
@@ -1,8 +1,8 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,7 +19,7 @@
%%
%%------------------------------------------------------------------------
%% File : hipe_dominators.erl
-%% Author : Christoffer Vikstr�m <[email protected]>
+%% Author : Christoffer Vikström <[email protected]>
%% Daniel Deogun <[email protected]>
%% Jesper Bengtsson <[email protected]>
%% Created : 18 Mar 2002
diff --git a/lib/hipe/icode/hipe_icode_mulret.erl b/lib/hipe/icode/hipe_icode_mulret.erl
index a3cae621ab..0bf9f89994 100644
--- a/lib/hipe/icode/hipe_icode_mulret.erl
+++ b/lib/hipe/icode/hipe_icode_mulret.erl
@@ -1,8 +1,8 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,9 +19,9 @@
%%
%%----------------------------------------------------------------------
%% File : hipe_icode_mulret.erl
-%% Author : Christoffer Vikstr�m <[email protected]>
+%% Author : Christoffer Vikström <[email protected]>
%% Purpose :
-%% Created : 23 Jun 2004 by Christoffer Vikstr�m <[email protected]>
+%% Created : 23 Jun 2004 by Christoffer Vikström <[email protected]>
%%----------------------------------------------------------------------
-module(hipe_icode_mulret).
@@ -890,7 +890,7 @@ removeUnElems([I|Code], [OldVar] = OldVars, DstLst, Res, Def, Lab) ->
%% [I|Res], Def, Lab)
%% end;
false ->
- io:format("Borde aldrig kunna hamna h�r!", []),
+ io:format("Borde aldrig kunna hamna här!", []),
removeUnElems(Code, OldVars, DstLst, [I|Res], Def, Lab)
end
end;
@@ -1159,8 +1159,8 @@ printCallList([]) -> io:format("~n").
%% % Purpose :
%% % Arguments :
%% % Return :
-%% % Notes : Fixa s� att funktionen anv�nder defines(I) ist�llet och
-%% % selektorer ist�llet f�r att matcha p� #call{}. L�tt gjort.
+%% % Notes : Fixa så att funktionen använder defines(I) istället och
+%% % selektorer istället för att matcha på #call{}. Lätt gjort.
%% %%>----------------------------------------------------------------------<
%% removeUnElems(List, Var) -> removeUnElems(List, Var, []).
%% removeUnElems([#icode_call{'fun'={unsafe_element,_}, args=Var}|List], Var, Res) ->
diff --git a/lib/hipe/regalloc/hipe_coalescing_regalloc.erl b/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
index 5a4b017c71..7169dd18f3 100644
--- a/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
@@ -1,8 +1,8 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,8 +20,8 @@
%%-----------------------------------------------------------------------
%% File : hipe_coalescing_regalloc.erl
%% Authors : Andreas Wallin <[email protected]>
-%% Thorild Sel�n <[email protected]>
-%% Ingemar �berg <[email protected]>
+%% Thorild Selén <[email protected]>
+%% Ingemar Åberg <[email protected]>
%% Purpose : Play paintball with registers on a target machine. We win
%% if they are all colored. This is an iterated coalescing
%% register allocator.
diff --git a/lib/hipe/regalloc/hipe_optimistic_regalloc.erl b/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
index 183ec1994c..fc3718cbc0 100644
--- a/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
@@ -1,8 +1,8 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1657,9 +1657,9 @@ findPrimitiveNodes(Node, N, Alias, PrimitiveNodes) ->
% %?debug_msg("Node ~p~n", [Node]),
% NextNode = Node - 1,
% Coalesced_to = hipe_reg_worklists:member_coalesced_to(NextNode, Worklists),
-% ?debug_msg("��-- member coalesced: ~p~n", [Coalesced_to]),
+% ?debug_msg("³³-- member coalesced: ~p~n", [Coalesced_to]),
% {Primitives, Alias1} = undoCoalescing(NextNode, No_temporaries, Alias),
-% ?debug_msg("��-- primitivenodes ~w\n", [Primitives]),
+% ?debug_msg("½½-- primitivenodes ~w\n", [Primitives]),
% case (Coalesced_to) of
% true -> printAlias(Alias1);
% _ -> true
@@ -1683,9 +1683,9 @@ findPrimitiveNodes(Node, N, Alias, PrimitiveNodes) ->
fixAdj(N, SavedAdj, IG, Target) ->
%Saved = hipe_vectors:get(SavedAdj, N),
Saved = hipe_adj_list:edges(N, SavedAdj),
- ?debug_msg("��--adj to ~p: ~p~n", [N, Saved]),
+ ?debug_msg("§§--adj to ~p: ~p~n", [N, Saved]),
Adj = hipe_ig:node_adj_list(N, IG),
- ?debug_msg("��--adj to ~p: ~p~n", [N, Adj]),
+ ?debug_msg("««--adj to ~p: ~p~n", [N, Adj]),
New = findNew(Adj, Saved),
?debug_msg("++--new adj to ~p: ~p~n", [N, New]),
removeAdj(New, N, IG, Target),
diff --git a/lib/hipe/regalloc/hipe_reg_worklists.erl b/lib/hipe/regalloc/hipe_reg_worklists.erl
index 67a5788c7c..e22cc8dc07 100644
--- a/lib/hipe/regalloc/hipe_reg_worklists.erl
+++ b/lib/hipe/regalloc/hipe_reg_worklists.erl
@@ -1,8 +1,8 @@
-%%% -*- erlang-indent-level: 2 -*-
+%%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%%
%%% The contents of this file are subject to the Erlang Public License,
%%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,7 +28,7 @@
%%%----------------------------------------------------------------------
-module(hipe_reg_worklists).
--author(['Andreas Wallin', 'Thorild Sel�n']).
+-author(['Andreas Wallin', 'Thorild Selén']).
-export([new/5, % only used by optimistic allocator
new/6,
simplify/1,
diff --git a/lib/hipe/rtl/hipe_rtl_arith.inc b/lib/hipe/rtl/hipe_rtl_arith.inc
index e608506234..7b587e882d 100644
--- a/lib/hipe/rtl/hipe_rtl_arith.inc
+++ b/lib/hipe/rtl/hipe_rtl_arith.inc
@@ -1,9 +1,9 @@
%% -*- Erlang -*-
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -114,7 +114,7 @@ eval_alu(Op, Arg1, Arg2)
eval_alu(Op, Arg1, Arg2) ->
?EXIT({argument_overflow,Op,Arg1,Arg2}).
-%% Bj�rn & Bjarni:
+%% Björn & Bjarni:
%% We need to be able to do evaluations based only on the bits, since
%% there are cases where we can evaluate a subset of the bits, but can
%% not do a full eval-alub call (eg. a + 0 gives no carry)
diff --git a/lib/hipe/rtl/hipe_rtl_mk_switch.erl b/lib/hipe/rtl/hipe_rtl_mk_switch.erl
index e5175217d6..d859c50b7d 100644
--- a/lib/hipe/rtl/hipe_rtl_mk_switch.erl
+++ b/lib/hipe/rtl/hipe_rtl_mk_switch.erl
@@ -1,8 +1,8 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -31,7 +31,7 @@
%% History : * 2001-02-28 Erik Johansson ([email protected]):
%% Created.
%% * 2001-04-01 Erik Trulsson ([email protected]):
-%% Stefan Lindstr�m ([email protected]):
+%% Stefan Lindström ([email protected]):
%% Added clustering and inlined binary search trees.
%% * 2001-07-30 EJ ([email protected]):
%% Fixed some bugs and started cleanup.
diff --git a/lib/hipe/rtl/hipe_rtl_primops.erl b/lib/hipe/rtl/hipe_rtl_primops.erl
index 53aaa72aa6..d9d08356ce 100644
--- a/lib/hipe/rtl/hipe_rtl_primops.erl
+++ b/lib/hipe/rtl/hipe_rtl_primops.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -738,7 +738,7 @@ gen_mkfun([Dst], {_Mod, _FunId, _Arity} = MFidA, MagicNr, Index, FreeVars) ->
%% Tag the thing and increase the heap_pointer.
%% make_fun(funp);
- WordSize�= hipe_rtl_arch:word_size(),
+ WordSize = hipe_rtl_arch:word_size(),
HeapNeed = (?ERL_FUN_SIZE + NumFree) * WordSize,
TagCode = [hipe_tagscheme:tag_fun(Dst, HP),
%% AdjustHPCode
@@ -829,7 +829,7 @@ load_struct_field(Dest, StructP, Offset, int32) ->
gen_free_vars(Vars, HPReg) ->
HPVar = hipe_rtl:mk_new_var(),
- WordSize�= hipe_rtl_arch:word_size(),
+ WordSize = hipe_rtl_arch:word_size(),
[hipe_rtl:mk_alu(HPVar, HPReg, add, hipe_rtl:mk_imm(?EFT_ENV)) |
gen_free_vars(Vars, HPVar, 0, WordSize, [])].
diff --git a/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl b/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
index 194cf29b64..1c900d767e 100644
--- a/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
+++ b/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
@@ -1,8 +1,8 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -190,7 +190,7 @@ set_to(Dst, Val, Env) ->
%% Returns : { FlowWorkList, SSAWorkList, NewEnvironment}
%%-----------------------------------------------------------------------------
-visit_branch(Inst, Env) -> %% Titta ocks� p� exekverbarflagga
+visit_branch(Inst, Env) -> %% Titta också på exekverbarflagga
Val1 = lookup_lattice_value(hipe_rtl:branch_src1(Inst), Env),
Val2 = lookup_lattice_value(hipe_rtl:branch_src2(Inst), Env),
CFGWL = case evaluate_relop(Val1, hipe_rtl:branch_cond(Inst), Val2) of
diff --git a/lib/hipe/rtl/hipe_rtl_ssapre.erl b/lib/hipe/rtl/hipe_rtl_ssapre.erl
index a9e92e5688..34897ba4b7 100644
--- a/lib/hipe/rtl/hipe_rtl_ssapre.erl
+++ b/lib/hipe/rtl/hipe_rtl_ssapre.erl
@@ -1,8 +1,8 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,7 +19,7 @@
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% File : hipe_rtl_ssapre.erl
-%% Author : He Bingwen and Fr�d�ric Haziza
+%% Author : He Bingwen and Frédéric Haziza
%% Description : Performs Partial Redundancy Elimination on SSA form.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% @doc
@@ -552,7 +552,7 @@ emend_with_processed_xsis(E, [I|Rest], Pred, XsiGraph) ->
true -> %% It's a computation of E!
case xsi_arg(Xsi,Pred) of
undetermined_operand ->
- exit({?MODULE,check_operand_sharing,"######## �h Dear, we trusted Kostis !!!!!!!!! #############"});
+ exit({?MODULE,check_operand_sharing,"######## Ôh Dear, we trusted Kostis !!!!!!!!! #############"});
XsiOp ->
{sharing_operand,XsiOp} %% They share operands
end;
@@ -571,7 +571,7 @@ emend_with_processed_xsis(E, [I|Rest], Pred, XsiGraph) ->
NewE = emend(E,Def,A#eop.var),
emend_with_processed_xsis(NewE,Rest,Pred,XsiGraph);
undetermined_operand ->
- exit({?MODULE,emend_with_processed_xsis,"######## �h Dear, we trusted Kostis, again !!!!!!!!! #############"});
+ exit({?MODULE,emend_with_processed_xsis,"######## Ôh Dear, we trusted Kostis, again !!!!!!!!! #############"});
XsiOp ->
NewE = emend(E,Def,XsiOp),
emend_with_processed_xsis(NewE,Rest,Pred,XsiGraph)
diff --git a/lib/hipe/ssa/hipe_ssa.inc b/lib/hipe/ssa/hipe_ssa.inc
index d15b5ddd56..e766a83c41 100644
--- a/lib/hipe/ssa/hipe_ssa.inc
+++ b/lib/hipe/ssa/hipe_ssa.inc
@@ -1,8 +1,8 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,7 +19,7 @@
%%
%%----------------------------------------------------------------------
%% File : hipe_ssa.inc
-%% Authors : Christoffer Vikstr�m, Daniel Deogun, and Jesper Bengtsson
+%% Authors : Christoffer Vikström, Daniel Deogun, and Jesper Bengtsson
%% Created : March 2002
%% Purpose : Provides code which converts the code of a CFG into SSA
%% (Static Single Assignment) form and back.
diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl
index 4e65736db3..7878c7219d 100644
--- a/lib/hipe/x86/hipe_x86_assemble.erl
+++ b/lib/hipe/x86/hipe_x86_assemble.erl
@@ -2,7 +2,7 @@
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%%
%%% The contents of this file are subject to the Erlang Public License,
%%% Version 1.1, (the "License"); you may not use this file except in
@@ -698,7 +698,7 @@ mem_to_ea_common(#x86_mem{base=#x86_temp{reg=Base}, off=#x86_imm{value=Off}}) ->
%% jmp_switch
-ifdef(HIPE_AMD64).
-resolve_jmp_switch_arg(I,�_Context) ->
+resolve_jmp_switch_arg(I, _Context) ->
Base = hipe_x86:temp_reg(hipe_x86:jmp_switch_jtab(I)),
Index = hipe_x86:temp_reg(hipe_x86:jmp_switch_temp(I)),
SINDEX = hipe_amd64_encode:sindex(3, Index),
diff --git a/lib/hipe/x86/hipe_x86_postpass.erl b/lib/hipe/x86/hipe_x86_postpass.erl
index 34e3d7a11b..c0918c4f89 100644
--- a/lib/hipe/x86/hipe_x86_postpass.erl
+++ b/lib/hipe/x86/hipe_x86_postpass.erl
@@ -1,8 +1,8 @@
-%%% -*- erlang-indent-level: 2 -*-
+%%% -*- coding: utf-8; erlang-indent-level: 2 -*-
%%%
%%% %CopyrightBegin%
%%%
-%%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%%
%%% The contents of this file are subject to the Erlang Public License,
%%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,9 +19,9 @@
%%%
%%%----------------------------------------------------------------------
%%% File : hipe_x86_postpass.erl
-%%% Author : Christoffer Vikstr�m <[email protected]>
+%%% Author : Christoffer Vikström <[email protected]>
%%% Purpose : Contain postpass optimisations for x86-assembler code.
-%%% Created : 5 Aug 2003 by Christoffer Vikstr�m <[email protected]>
+%%% Created : 5 Aug 2003 by Christoffer Vikström <[email protected]>
%%%----------------------------------------------------------------------
-ifndef(HIPE_X86_POSTPASS).
diff --git a/lib/hipe/x86/hipe_x86_ra_postconditions.erl b/lib/hipe/x86/hipe_x86_ra_postconditions.erl
index 0b70764daf..6d7e90df43 100644
--- a/lib/hipe/x86/hipe_x86_ra_postconditions.erl
+++ b/lib/hipe/x86/hipe_x86_ra_postconditions.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -224,7 +224,7 @@ do_byte_move(Src0, Dst0, TempMap, Strategy) ->
do_move64(I, TempMap, Strategy) ->
#move64{dst=Dst} = I,
- case�is_spilled(Dst, TempMap) of
+ case is_spilled(Dst, TempMap) of
false ->
{[I], false};
true ->
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index bd31ae42d2..d9e8587bbf 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>2012</year>
+ <year>2012</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -55,7 +55,8 @@ string() = list of ASCII characters
<p>For more information about URI, see RFC 3986. </p>
<code type="none"><![CDATA[
-uri() = string() - Syntax according to the URI definition in rfc 3986, ex: "http://www.erlang.org/"
+uri() = string() - Syntax according to the URI definition in rfc 3986,
+ e.g.: "http://www.erlang.org/"
user_info() = string()
scheme() = atom() - Example: http, https
host() = string()
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
index d5388e54f4..c91c743498 100644
--- a/lib/jinterface/test/nc_SUITE.erl
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -361,8 +362,8 @@ unicode(doc) -> [];
unicode(suite) -> [];
unicode(Config) when is_list(Config) ->
S1 = "plain ascii",
- S2 = "iso-latin ��� �",
- S3 = "Codepoints... ��� \x{1000}",
+ S2 = "iso-latin åäö ñ",
+ S3 = "Codepoints... åäö \x{1000}",
S4 = [0,1,31,32,63,64,127,128,255],
S5 = [0,1,127,128,255,256,16#d7ff,
16#e000,16#fffd,16#10000,16#10ffff],
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index 5e04bff0c1..de3ca1e176 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -58,7 +58,6 @@ XML_REF3_FILES = application.xml \
net_adm.xml \
net_kernel.xml \
os.xml \
- packages.xml \
pg2.xml \
rpc.xml \
seq_trace.xml \
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index b2a259080d..536b98b5f5 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -110,7 +110,7 @@
<desc>
<p>As returned by
<seealso marker="#open/2">file:open/2</seealso>,
- a process handling IO protocols.</p>
+ a process handling I/O-protocols.</p>
</desc>
</datatype>
<datatype>
@@ -261,6 +261,9 @@
{person, "pelle", 30}.</code>
<pre>1> <input>file:consult("f.txt").</input>
{ok,[{person,"kalle",25},{person,"pelle",30}]}</pre>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
@@ -399,6 +402,9 @@
of the error.</p>
</item>
</taglist>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
@@ -610,7 +616,7 @@
<name name="open" arity="2"/>
<fsummary>Open a file</fsummary>
<desc>
- <p>Opens the file <c><anno>Filename</anno></c> in the mode determined
+ <p>Opens the file <c><anno>File</anno></c> in the mode determined
by <c><anno>Modes</anno></c>, which may contain one or more of the
following items:</p>
<taglist>
@@ -767,6 +773,10 @@
<p>The Encoding can be changed for a file "on the fly" by using the <seealso marker="stdlib:io#setopts/2">io:setopts/2</seealso> function, why a file can be analyzed in latin1 encoding for i.e. a BOM, positioned beyond the BOM and then be set for the right encoding before further reading.See the <seealso marker="stdlib:unicode">unicode(3)</seealso> module for functions identifying BOM's.</p>
<p>This option is not allowed on <c>raw</c> files.</p>
</item>
+ <tag><c>ram</c></tag>
+ <item>
+ <p><c>File</c> must be <c>iodata()</c>. Returns an <c>fd()</c> which lets the <c>file</c> module operate on the data in-memory as if it is a file.</p>
+ </item>
</taglist>
<p>Returns:</p>
<taglist>
@@ -861,6 +871,9 @@
the error.</p>
</item>
</taglist>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
@@ -902,6 +915,9 @@
of the error.</p>
</item>
</taglist>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
@@ -971,7 +987,10 @@
of the error.</p>
</item>
</taglist>
- </desc>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
+ </desc>
</func>
<func>
<name name="path_script" arity="3"/>
@@ -1502,6 +1521,9 @@
of the error.</p>
</item>
</taglist>
+ <p>The encoding of of <c><anno>Filename</anno></c> can be set
+ by a comment as described in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index a1590c2dce..3d929a772e 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -323,8 +323,11 @@ fe80::204:acff:fe17:bf38
<type name="stat_option"/>
<desc>
<p>Gets one or more statistic options for a socket.</p>
+
<p><c>getstat(<anno>Socket</anno>)</c> is equivalent to
- <c>getstat(<anno>Socket</anno>,&nbsp;[recv_avg,&nbsp;recv_cnt,&nbsp;recv_dvi,&nbsp;recv_max,&nbsp;recv_oct,&nbsp;send_avg,&nbsp;send_cnt,&nbsp;send_dvi,&nbsp;send_max,&nbsp;send_oct])</c></p>
+ <c>getstat(<anno>Socket</anno>, [recv_avg, recv_cnt, recv_dvi,
+ recv_max, recv_oct, send_avg, send_cnt, send_dvi, send_max,
+ send_oct])</c>.</p>
<p>The following options are available:</p>
<taglist>
<tag><c>recv_avg</c></tag>
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index c76ff9e2f0..60291bbce6 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -107,7 +107,6 @@ MODULES = \
net_adm \
net_kernel \
os \
- packages \
pg2 \
ram_file \
rpc \
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index c808ac7cb7..361f2bdf8a 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -359,7 +359,6 @@ load_code_server_prerequisites() ->
hipe_unified_loader,
lists,
os,
- packages,
unicode],
[M = M:module_info(module) || M <- Needed],
ok.
@@ -413,7 +412,7 @@ which(Module) when is_atom(Module) ->
end.
which2(Module) ->
- Base = to_path(Module),
+ Base = atom_to_list(Module),
File = filename:basename(Base) ++ objfile_extension(),
Path = get_path(),
which(File, filename:dirname(Base), Path).
@@ -547,9 +546,6 @@ has_ext(Ext, Extlen, File) ->
_ -> false
end.
-to_path(X) ->
- filename:join(packages:split(X)).
-
-spec load_native_code_for_all_loaded() -> ok.
load_native_code_for_all_loaded() ->
Architecture = erlang:system_info(hipe_architecture),
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 00ad923466..b2d2c19f78 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1229,7 +1229,7 @@ load_abs(File, Mod0, Caller, St) ->
end.
try_load_module(Mod, Dir, Caller, St) ->
- File = filename:append(Dir, to_path(Mod) ++
+ File = filename:append(Dir, to_list(Mod) ++
objfile_extension()),
case erl_prim_loader:get_file(File) of
error ->
@@ -1347,7 +1347,7 @@ load_file_1(Mod, Caller, #state{cache=Cache}=St0) ->
end.
mod_to_bin([Dir|Tail], Mod) ->
- File = filename:append(Dir, to_path(Mod) ++ objfile_extension()),
+ File = filename:append(Dir, to_list(Mod) ++ objfile_extension()),
case erl_prim_loader:get_file(File) of
error ->
mod_to_bin(Tail, Mod);
@@ -1356,7 +1356,7 @@ mod_to_bin([Dir|Tail], Mod) ->
end;
mod_to_bin([], Mod) ->
%% At last, try also erl_prim_loader's own method
- File = to_path(Mod) ++ objfile_extension(),
+ File = to_list(Mod) ++ objfile_extension(),
case erl_prim_loader:get_file(File) of
error ->
error; % No more alternatives !
@@ -1570,6 +1570,3 @@ to_list(X) when is_atom(X) -> atom_to_list(X).
to_atom(X) when is_atom(X) -> X;
to_atom(X) when is_list(X) -> list_to_atom(X).
-
-to_path(X) ->
- filename:join(packages:split(X)).
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index f0d54a2f3e..e3511988a6 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -757,7 +757,8 @@ setup_timer(Pid, Timeout) ->
end.
reset_timer(Timer) ->
- Timer ! {self(), reset}.
+ Timer ! {self(), reset},
+ ok.
cancel_timer(Timer) ->
unlink(Timer),
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 22af38c598..de3eaad5a1 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -397,9 +397,10 @@ raw_write_file_info(Name, #file_info{} = Info) ->
%% Contemporary mode specification - list of options
--spec open(Filename, Modes) -> {ok, IoDevice} | {error, Reason} when
+-spec open(File, Modes) -> {ok, IoDevice} | {error, Reason} when
+ File :: Filename | iodata(),
Filename :: name(),
- Modes :: [mode()],
+ Modes :: [mode() | ram],
IoDevice :: io_device(),
Reason :: posix() | badarg | system_limit.
@@ -1314,6 +1315,7 @@ sendfile_send(Sock, Data, Old) ->
%%% Helpers
consult_stream(Fd) ->
+ _ = epp:set_encoding(Fd),
consult_stream(Fd, 1, []).
consult_stream(Fd, Line, Acc) ->
@@ -1327,6 +1329,7 @@ consult_stream(Fd, Line, Acc) ->
end.
eval_stream(Fd, Handling, Bs) ->
+ _ = epp:set_encoding(Fd),
eval_stream(Fd, Handling, 1, undefined, [], Bs).
eval_stream(Fd, H, Line, Last, E, Bs) ->
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index 0bff56cf46..acaffe1e41 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -40,6 +40,8 @@ format_error({_Line, ?MODULE, Reason}) ->
io_lib:format("~w", [Reason]);
format_error({_Line, Mod, Reason}) ->
Mod:format_error(Reason);
+format_error(invalid_unicode) ->
+ io_lib:format("cannot translate from UTF-8", []);
format_error(ErrorId) ->
erl_posix_msg:message(ErrorId).
@@ -549,7 +551,7 @@ get_chars_notempty(Mod, Func, XtraArg, S, OutEnc,
<<>> ->
get_chars_apply(Mod, Func, XtraArg, S, OutEnc, State, eof);
_ ->
- {stop,invalid_unicode,{error,invalid_unicode},State}
+ {stop,invalid_unicode,invalid_unicode_error(Mod, Func, XtraArg, S),State}
end;
{error,Reason}=Error ->
{stop,Reason,Error,State}
@@ -616,12 +618,22 @@ get_chars_apply(Mod, Func, XtraArg, S0, OutEnc,
end
catch
exit:ExReason ->
- {stop,ExReason,{error,err_func(Mod, Func, XtraArg)},State};
+ {stop,ExReason,invalid_unicode_error(Mod, Func, XtraArg, S0),State};
error:ErrReason ->
{stop,ErrReason,{error,err_func(Mod, Func, XtraArg)},State}
end.
-
+%% A hack that tries to inform the caller about the position where the
+%% error occured.
+invalid_unicode_error(Mod, Func, XtraArg, S) ->
+ try
+ {erl_scan,tokens,_Args} = XtraArg,
+ Location = erl_scan:continuation_location(S),
+ {error,{Location, ?MODULE, invalid_unicode},Location}
+ catch
+ _:_ ->
+ {error,err_func(Mod, Func, XtraArg)}
+ end.
%% Convert error code to make it look as before
err_func(io_lib, get_until, {_,F,_}) ->
diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl
index f92c6f7208..4d2e31a429 100644
--- a/lib/kernel/src/group.erl
+++ b/lib/kernel/src/group.erl
@@ -424,7 +424,7 @@ get_password_chars(Drv,Buf) ->
end.
get_chars(Prompt, M, F, Xa, Drv, Buf, Encoding) ->
- Pbs = prompt_bytes(Prompt),
+ Pbs = prompt_bytes(Prompt, Encoding),
get_chars_loop(Pbs, M, F, Xa, Drv, Buf, start, Encoding).
get_chars_loop(Pbs, M, F, Xa, Drv, Buf0, State, Encoding) ->
@@ -688,9 +688,9 @@ edit_password([Char|Cs],Chars) ->
edit_password(Cs,[Char|Chars]).
%% prompt_bytes(Prompt)
-%% Return a flat list of bytes for the Prompt.
-prompt_bytes(Prompt) ->
- lists:flatten(io_lib:format_prompt(Prompt)).
+%% Return a flat list of characters for the Prompt.
+prompt_bytes(Prompt, Encoding) ->
+ lists:flatten(io_lib:format_prompt(Prompt, Encoding)).
cast(L, binary,latin1) when is_list(L) ->
list_to_binary(L);
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 17ab84c177..9a20baf8d0 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -28,7 +28,6 @@
application_starter,
auth,
code,
- packages,
code_server,
dist_util,
erl_boot_server,
diff --git a/lib/kernel/src/packages.erl b/lib/kernel/src/packages.erl
deleted file mode 100644
index e0b1f36b85..0000000000
--- a/lib/kernel/src/packages.erl
+++ /dev/null
@@ -1,158 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(packages).
-
--export([to_string/1, concat/1, concat/2, is_valid/1, is_segmented/1,
- split/1, last/1, first/1, strip_last/1, find_modules/1,
- find_modules/2]).
-
-%% A package name (or a package-qualified module name) may be an atom or
-%% a string (list of nonnegative integers) - not a deep list, and not a
-%% list containing atoms. A name may be empty, but may not contain two
-%% consecutive period (`.') characters or end with a period character.
-
--type package_name() :: atom() | string().
-
--spec to_string(package_name()) -> string().
-to_string(Name) when is_atom(Name) ->
- atom_to_list(Name);
-to_string(Name) ->
- Name.
-
-%% `concat' does not insert a leading period if the first segment is
-%% empty. However, the result may contain leading, consecutive or
-%% dangling period characters, if any of the segments after the first
-%% are empty. Use 'is_valid' to check the result if necessary.
-
--spec concat(package_name(), package_name()) -> string().
-concat(A, B) ->
- concat([A, B]).
-
--spec concat([package_name()]) -> string().
-concat([H | T]) when is_atom(H) ->
- concat([atom_to_list(H) | T]);
-concat(["" | T]) ->
- concat_1(T);
-concat(L) ->
- concat_1(L).
-
-concat_1([H | T]) when is_atom(H) ->
- concat_1([atom_to_list(H) | T]);
-concat_1([H]) ->
- H;
-concat_1([H | T]) ->
- H ++ "." ++ concat_1(T);
-concat_1([]) ->
- "";
-concat_1(Name) ->
- erlang:error({badarg, Name}).
-
--spec is_valid(package_name()) -> boolean().
-is_valid(Name) when is_atom(Name) ->
- is_valid_1(atom_to_list(Name));
-is_valid([$. | _]) ->
- false;
-is_valid(Name) ->
- is_valid_1(Name).
-
-is_valid_1([$.]) -> false;
-is_valid_1([$., $. | _]) -> false;
-is_valid_1([H | T]) when is_integer(H), H >= 0 ->
- is_valid_1(T);
-is_valid_1([]) -> true;
-is_valid_1(_) -> false.
-
--spec split(package_name()) -> [string()].
-split(Name) when is_atom(Name) ->
- split_1(atom_to_list(Name), []);
-split(Name) ->
- split_1(Name, []).
-
-split_1([$. | T], Cs) ->
- [lists:reverse(Cs) | split_1(T, [])];
-split_1([H | T], Cs) when is_integer(H), H >= 0 ->
- split_1(T, [H | Cs]);
-split_1([], Cs) ->
- [lists:reverse(Cs)];
-split_1(_, _) ->
- erlang:error(badarg).
-
-%% This is equivalent to testing if `split(Name)' yields a list of
-%% length larger than one (i.e., if the name can be split into two or
-%% more segments), but is cheaper.
-
--spec is_segmented(package_name()) -> boolean().
-is_segmented(Name) when is_atom(Name) ->
- is_segmented_1(atom_to_list(Name));
-is_segmented(Name) ->
- is_segmented_1(Name).
-
-is_segmented_1([$. | _]) -> true;
-is_segmented_1([H | T]) when is_integer(H), H >= 0 ->
- is_segmented_1(T);
-is_segmented_1([]) -> false;
-is_segmented_1(_) ->
- erlang:error(badarg).
-
--spec last(package_name()) -> string().
-last(Name) ->
- last_1(split(Name)).
-
-last_1([H]) -> H;
-last_1([_ | T]) -> last_1(T).
-
--spec first(package_name()) -> [string()].
-first(Name) ->
- first_1(split(Name)).
-
-first_1([H | T]) when T =/= [] -> [H | first_1(T)];
-first_1(_) -> [].
-
--spec strip_last(package_name()) -> string().
-strip_last(Name) ->
- concat(first(Name)).
-
-%% This finds all modules available for a given package, using the
-%% current code server search path. (There is no guarantee that the
-%% modules are loadable; only that the object files exist.)
-
--spec find_modules(package_name()) -> [string()].
-find_modules(P) ->
- find_modules(P, code:get_path()).
-
--spec find_modules(package_name(), [string()]) -> [string()].
-find_modules(P, Paths) ->
- P1 = filename:join(packages:split(P)),
- find_modules(P1, Paths, code:objfile_extension(), sets:new()).
-
-find_modules(P, [Path | Paths], Ext, S0) ->
- case file:list_dir(filename:join(Path, P)) of
- {ok, Fs} ->
- Fs1 = [F || F <- Fs, filename:extension(F) =:= Ext],
- S1 = lists:foldl(fun (F, S) ->
- F1 = filename:rootname(F, Ext),
- sets:add_element(F1, S)
- end,
- S0, Fs1),
- find_modules(P, Paths, Ext, S1);
- _ ->
- find_modules(P, Paths, Ext, S0)
- end;
-find_modules(_P, [], _Ext, S) ->
- sets:to_list(S).
diff --git a/lib/kernel/src/user.erl b/lib/kernel/src/user.erl
index 88f32df20b..d6449d9e5e 100644
--- a/lib/kernel/src/user.erl
+++ b/lib/kernel/src/user.erl
@@ -81,7 +81,7 @@ server(PortName,PortSettings) ->
run(P) ->
put(read_mode,list),
- put(unicode,false),
+ put(encoding,latin1),
case init:get_argument(noshell) of
%% non-empty list -> noshell
{ok, [_|_]} ->
@@ -191,39 +191,27 @@ do_io_request(Req, From, ReplyAs, Port, Q0) ->
%% New in R13B
%% Encoding option (unicode/latin1)
io_request({put_chars,unicode,Chars}, Port, Q) -> % Binary new in R9C
- put_chars(wrap_characters_to_binary(Chars,unicode,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end), Port, Q);
+ put_chars(wrap_characters_to_binary(Chars,unicode, get(encoding)), Port, Q);
io_request({put_chars,unicode,Mod,Func,Args}, Port, Q) ->
Result = case catch apply(Mod,Func,Args) of
Data when is_list(Data); is_binary(Data) ->
- wrap_characters_to_binary(Data,unicode,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end);
+ wrap_characters_to_binary(Data,unicode,get(encoding));
Undef ->
Undef
end,
put_chars(Result, Port, Q);
io_request({put_chars,latin1,Chars}, Port, Q) -> % Binary new in R9C
- Data = case get(unicode) of
- true ->
+ Data = case get(encoding) of
+ unicode ->
unicode:characters_to_binary(Chars,latin1,unicode);
- false ->
+ latin1 ->
erlang:iolist_to_binary(Chars)
end,
put_chars(Data, Port, Q);
io_request({put_chars,latin1,Mod,Func,Args}, Port, Q) ->
Result = case catch apply(Mod,Func,Args) of
Data when is_list(Data); is_binary(Data) ->
- unicode:characters_to_binary(Data,latin1,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end);
+ unicode:characters_to_binary(Data,latin1,get(encoding));
Undef ->
Undef
end,
@@ -351,9 +339,9 @@ check_valid_opts(_) ->
do_setopts(Opts, _Port, Q) ->
case proplists:get_value(encoding,Opts) of
Valid when Valid =:= unicode; Valid =:= utf8 ->
- put(unicode,true);
+ put(encoding,unicode);
latin1 ->
- put(unicode,false);
+ put(encoding,latin1);
undefined ->
ok
end,
@@ -370,12 +358,7 @@ do_setopts(Opts, _Port, Q) ->
getopts(_Port,Q) ->
Bin = {binary, get(read_mode) =:= binary},
- Uni = {encoding, case get(unicode) of
- true ->
- unicode;
- _ ->
- latin1
- end},
+ Uni = {encoding, get(encoding)},
{ok,[Bin,Uni],Q}.
@@ -575,31 +558,32 @@ binrev(L, T) ->
%% end
%% end
%% end.
-%% get_chars(Prompt, Module, Function, XtraArg, Port, Queue)
+%% get_chars(Prompt, Module, Function, XtraArg, Port, Queue, Encoding)
%% Gets characters from the input port until the applied function
%% returns {stop,Result,RestBuf}. Does not block output until input
-%% has been received.
+%% has been received. Encoding is the encoding of the data sent to
+%% the client and to Function.
%% Returns:
%% {Status,Result,NewQueue}
%% {exit,Reason}
%% Entry function.
-get_chars(Prompt, M, F, Xa, Port, Q, Fmt) ->
+get_chars(Prompt, M, F, Xa, Port, Q, Enc) ->
prompt(Port, Prompt),
case {get(eof),queue:is_empty(Q)} of
{true,true} ->
{ok,eof,Q};
_ ->
- get_chars(Prompt, M, F, Xa, Port, Q, start, Fmt)
+ get_chars(Prompt, M, F, Xa, Port, Q, start, Enc)
end.
%% First loop. Wait for port data. Respond to output requests.
-get_chars(Prompt, M, F, Xa, Port, Q, State, Fmt) ->
+get_chars(Prompt, M, F, Xa, Port, Q, State, Enc) ->
case queue:is_empty(Q) of
true ->
receive
{Port,{data,Bytes}} ->
- get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Fmt);
+ get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Enc);
{Port, eof} ->
put(eof, true),
{ok, eof, []};
@@ -610,41 +594,41 @@ get_chars(Prompt, M, F, Xa, Port, Q, State, Fmt) ->
do_io_request(Req, From, ReplyAs, Port,
queue:new()), %Keep Q over this call
%% No prompt.
- get_chars(Prompt, M, F, Xa, Port, Q, State, Fmt);
+ get_chars(Prompt, M, F, Xa, Port, Q, State, Enc);
{io_request,From,ReplyAs,Request} when is_pid(From) ->
get_chars_req(Prompt, M, F, Xa, Port, Q, State,
- Request, From, ReplyAs, Fmt);
+ Request, From, ReplyAs, Enc);
{'EXIT',From,What} when node(From) =:= node() ->
{exit,What}
end;
false ->
- get_chars_apply(State, M, F, Xa, Port, Q, Fmt)
+ get_chars_apply(State, M, F, Xa, Port, Q, Enc)
end.
get_chars_req(Prompt, M, F, XtraArg, Port, Q, State,
- Req, From, ReplyAs, Fmt) ->
+ Req, From, ReplyAs, Enc) ->
do_io_request(Req, From, ReplyAs, Port, queue:new()), %Keep Q over this call
prompt(Port, Prompt),
- get_chars(Prompt, M, F, XtraArg, Port, Q, State, Fmt).
+ get_chars(Prompt, M, F, XtraArg, Port, Q, State, Enc).
%% Second loop. Pass data to client as long as it wants more.
%% A ^G in data interrupts loop if 'noshell' is not undefined.
-get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Fmt) ->
+get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Enc) ->
case get(shell) of
noshell ->
- get_chars_apply(State, M, F, Xa, Port, queue:snoc(Q, Bytes),Fmt);
+ get_chars_apply(State, M, F, Xa, Port, queue:snoc(Q, Bytes),Enc);
_ ->
case contains_ctrl_g_or_ctrl_c(Bytes) of
false ->
get_chars_apply(State, M, F, Xa, Port,
- queue:snoc(Q, Bytes),Fmt);
+ queue:snoc(Q, Bytes),Enc);
_ ->
throw(new_shell)
end
end.
-get_chars_apply(State0, M, F, Xa, Port, Q, Fmt) ->
- case catch M:F(State0, cast(queue:head(Q),Fmt), Fmt, Xa) of
+get_chars_apply(State0, M, F, Xa, Port, Q, Enc) ->
+ case catch M:F(State0, cast(queue:head(Q),Enc), Enc, Xa) of
{stop,Result,<<>>} ->
{ok,Result,queue:tail(Q)};
{stop,Result,[]} ->
@@ -653,32 +637,32 @@ get_chars_apply(State0, M, F, Xa, Port, Q, Fmt) ->
{ok,Result,queue:tail(Q)};
{stop,Result,Buf} ->
{ok,Result,queue:cons(Buf, queue:tail(Q))};
- {'EXIT',_} ->
+ {'EXIT',_Why} ->
{error,{error,err_func(M, F, Xa)},queue:new()};
State1 ->
- get_chars_more(State1, M, F, Xa, Port, queue:tail(Q), Fmt)
+ get_chars_more(State1, M, F, Xa, Port, queue:tail(Q), Enc)
end.
-get_chars_more(State, M, F, Xa, Port, Q, Fmt) ->
+get_chars_more(State, M, F, Xa, Port, Q, Enc) ->
case queue:is_empty(Q) of
true ->
case get(eof) of
undefined ->
receive
{Port,{data,Bytes}} ->
- get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Fmt);
+ get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Enc);
{Port,eof} ->
put(eof, true),
get_chars_apply(State, M, F, Xa, Port,
- queue:snoc(Q, eof), Fmt);
+ queue:snoc(Q, eof), Enc);
{'EXIT',From,What} when node(From) =:= node() ->
{exit,What}
end;
_ ->
- get_chars_apply(State, M, F, Xa, Port, queue:snoc(Q, eof), Fmt)
+ get_chars_apply(State, M, F, Xa, Port, queue:snoc(Q, eof), Enc)
end;
false ->
- get_chars_apply(State, M, F, Xa, Port, Q, Fmt)
+ get_chars_apply(State, M, F, Xa, Port, Q, Enc)
end.
@@ -689,11 +673,10 @@ get_chars_more(State, M, F, Xa, Port, Q, Fmt) ->
prompt(_Port, '') -> ok;
prompt(Port, Prompt) ->
- put_port(wrap_characters_to_binary(io_lib:format_prompt(Prompt),unicode,
- case get(unicode) of
- true -> unicode;
- _ -> latin1
- end), Port).
+ Encoding = get(encoding),
+ put_port(wrap_characters_to_binary(io_lib:format_prompt(Prompt, Encoding),
+ unicode, Encoding),
+ Port).
%% Convert error code to make it look as before
err_func(io_lib, get_until, {_,F,_}) ->
@@ -710,56 +693,65 @@ contains_ctrl_g_or_ctrl_c(BinOrList)->
end.
%% Convert a buffer between list and binary
-cast(Data, _Format) when is_atom(Data) ->
+cast(Data, _Encoding) when is_atom(Data) ->
Data;
-cast(Data, Format) ->
- cast(Data, get(read_mode), Format, get(unicode)).
+cast(Data, Encoding) ->
+ IoEncoding = get(encoding),
+ cast(Data, get(read_mode), IoEncoding, Encoding).
-cast(B, binary, latin1, false) when is_binary(B) ->
+cast(B, binary, latin1, latin1) when is_binary(B) ->
B;
-cast(B, binary, latin1, true) when is_binary(B) ->
- unicode:characters_to_binary(B, unicode, latin1);
-cast(L, binary, latin1, false) ->
- erlang:iolist_to_binary(L);
-cast(L, binary, latin1, true) ->
- case unicode:characters_to_binary(
- erlang:iolist_to_binary(L),unicode,latin1) of % may fail
- {error,_,_} -> exit({no_translation, unicode, latin1});
- Else -> Else
+cast(L, binary, latin1, latin1) ->
+ case catch erlang:iolist_to_binary(L) of
+ Bin when is_binary(Bin) -> Bin;
+ _ -> exit({no_translation, latin1, latin1})
+ end;
+cast(Data, binary, unicode, latin1) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_binary(Data, unicode, latin1) of
+ Bin when is_binary(Bin) -> Bin;
+ _ -> exit({no_translation, unicode, latin1})
+ end;
+cast(Data, binary, latin1, unicode) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_binary(Data, latin1, unicode) of
+ Bin when is_binary(Bin) -> Bin;
+ _ -> exit({no_translation, latin1, unicode})
end;
-cast(B, binary, unicode, true) when is_binary(B) ->
+cast(B, binary, unicode, unicode) when is_binary(B) ->
B;
-cast(B, binary, unicode, false) when is_binary(B) ->
- unicode:characters_to_binary(B,latin1,unicode);
-cast(L, binary, unicode, true) ->
- % possibly a list containing UTF-8 encoded characters
- unicode:characters_to_binary(erlang:iolist_to_binary(L));
-cast(L, binary, unicode, false) ->
- unicode:characters_to_binary(L, latin1, unicode);
-cast(L, list, latin1, UniTerm) ->
- case UniTerm of
- true -> % Convert input characters to protocol format (i.e latin1)
- case unicode:characters_to_list(
- erlang:iolist_to_binary(L),unicode) of % may fail
- {error,_,_} -> exit({no_translation, unicode, latin1});
- Else -> [ case X of
- High when High > 255 ->
- exit({no_translation, unicode, latin1});
- Low ->
- Low
- end || X <- Else ]
- end;
- _ ->
- binary_to_list(erlang:iolist_to_binary(L))
+cast(L, binary, unicode, unicode) ->
+ case catch unicode:characters_to_binary(L, unicode) of
+ Bin when is_binary(Bin) -> Bin;
+ _ -> exit({no_translation, unicode, unicode})
end;
-cast(L, list, unicode, UniTerm) ->
- unicode:characters_to_list(erlang:iolist_to_binary(L),
- case UniTerm of
- true -> unicode;
- _ -> latin1
- end);
-cast(Other, _, _,_) ->
- Other.
+cast(B, list, latin1, latin1) when is_binary(B) ->
+ binary_to_list(B);
+cast(L, list, latin1, latin1) ->
+ case catch erlang:iolist_to_binary(L) of
+ Bin when is_binary(Bin) -> binary_to_list(Bin);
+ _ -> exit({no_translation, latin1, latin1})
+ end;
+cast(Data, list, unicode, latin1) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_list(Data, unicode) of
+ Chars when is_list(Chars) ->
+ [ case X of
+ High when High > 255 ->
+ exit({no_translation, unicode, latin1});
+ Low ->
+ Low
+ end || X <- Chars ];
+ _ ->
+ exit({no_translation, unicode, latin1})
+ end;
+cast(Data, list, latin1, unicode) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_list(Data, latin1) of
+ Chars when is_list(Chars) -> Chars;
+ _ -> exit({no_translation, latin1, unicode})
+ end;
+cast(Data, list, unicode, unicode) when is_binary(Data); is_list(Data) ->
+ case catch unicode:characters_to_list(Data, unicode) of
+ Chars when is_list(Chars) -> Chars;
+ _ -> exit({no_translation, unicode, unicode})
+ end.
wrap_characters_to_binary(Chars,unicode,latin1) ->
case unicode:characters_to_binary(Chars,unicode,latin1) of
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 8eca37029d..7fd3afe93c 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -73,6 +73,7 @@ MODULES= \
seq_trace_SUITE \
wrap_log_reader_SUITE \
cleanup \
+ ignore_cores \
zlib_SUITE \
loose_node \
sendfile_SUITE
diff --git a/lib/kernel/test/error_logger_warn_SUITE.erl b/lib/kernel/test/error_logger_warn_SUITE.erl
index 265e1ae4c8..2bf467610e 100644
--- a/lib/kernel/test/error_logger_warn_SUITE.erl
+++ b/lib/kernel/test/error_logger_warn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -310,7 +310,7 @@ nice_stop_node(Name) ->
{nodedown,Name} -> ok
end.
-%rensa rd() f�re varje rapport-test s� man bara f�r en fil...
+%clean out rd() before each report test in order to get only one file...
clean_rd() ->
{ok,L} = file:list_dir(rd()),
lists:foreach(fun(F) ->
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 3aa010a708..40bde8a736 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -1,4 +1,5 @@
-module(file_name_SUITE).
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -336,7 +337,7 @@ check_normal(Mod) ->
check_icky(Mod) ->
{ok,Dir} = Mod:get_cwd(),
try
- ?line true=(length("���") =:= 3),
+ ?line true=(length("åäö") =:= 3),
?line UniMode = file:native_name_encoding() =/= latin1,
?line make_icky_dir(Mod),
?line {ok, L0} = Mod:list_dir("."),
@@ -357,42 +358,42 @@ check_icky(Mod) ->
|| {T,S,Targ} <- icky_dir(), T =:= symlink ],
?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
?line [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ],
- ?line chk_cre_dir(Mod,[{directory,"���_dir",icky_dir()}]),
+ ?line chk_cre_dir(Mod,[{directory,"åäö_dir",icky_dir()}]),
?line {ok,BeginAt} = Mod:get_cwd(),
?line true = is_list(BeginAt),
- ?line {error,enoent} = Mod:set_cwd("��_dir"),
- ?line ok = Mod:set_cwd("���_dir"),
+ ?line {error,enoent} = Mod:set_cwd("åä_dir"),
+ ?line ok = Mod:set_cwd("åäö_dir"),
?line {ok, NowAt} = Mod:get_cwd(),
?line true = is_list(NowAt),
?line true = BeginAt =/= NowAt,
?line ok = Mod:set_cwd(".."),
?line {ok,BeginAt} = Mod:get_cwd(),
- ?line rm_r2(Mod,"���_dir"),
+ ?line rm_r2(Mod,"åäö_dir"),
{OS,TYPE} = os:type(),
% Check that treat_icky really converts to the same as the OS
case UniMode of
true ->
- ?line chk_cre_dir(Mod,[{directory,"���_dir",[]}]),
- ?line ok = Mod:set_cwd("���_dir"),
- ?line ok = Mod:write_file(<<"���">>,<<"hello">>),
- ?line Treated = treat_icky(<<"���">>),
+ ?line chk_cre_dir(Mod,[{directory,"åäö_dir",[]}]),
+ ?line ok = Mod:set_cwd("åäö_dir"),
+ ?line ok = Mod:write_file(<<"ååå">>,<<"hello">>),
+ ?line Treated = treat_icky(<<"ååå">>),
?line {ok,[Treated]} = Mod:list_dir("."),
- ?line ok = Mod:delete(<<"���">>),
+ ?line ok = Mod:delete(<<"ååå">>),
?line {ok,[]} = Mod:list_dir("."),
?line ok = Mod:set_cwd(".."),
- ?line rm_r2(Mod,"���_dir");
+ ?line rm_r2(Mod,"åäö_dir");
false ->
ok
end,
- ?line chk_cre_dir(Mod,[{directory,treat_icky(<<"���_dir">>),icky_dir()}]),
+ ?line chk_cre_dir(Mod,[{directory,treat_icky(<<"åäö_dir">>),icky_dir()}]),
if
UniMode and (OS =/= win32) ->
- ?line {error,enoent} = Mod:set_cwd("���_dir");
+ ?line {error,enoent} = Mod:set_cwd("åäö_dir");
true ->
ok
end,
- ?line ok = Mod:set_cwd(treat_icky(<<"���_dir">>)),
+ ?line ok = Mod:set_cwd(treat_icky(<<"åäö_dir">>)),
?line {ok, NowAt2} = Mod:get_cwd(),
io:format("~p~n",[NowAt2]),
% Cannot create raw unicode-breaking filenames on windows or macos
@@ -400,22 +401,22 @@ check_icky(Mod) ->
?line true = BeginAt =/= NowAt2,
?line ok = Mod:set_cwd(".."),
?line {ok,BeginAt} = Mod:get_cwd(),
- ?line rm_r2(Mod,conv(treat_icky(<<"���_dir">>))),
+ ?line rm_r2(Mod,conv(treat_icky(<<"åäö_dir">>))),
case has_links() of
true ->
- ?line ok = Mod:make_link("fil1","nisse�"),
- ?line {ok, <<"fil1">>} = Mod:read_file("nisse�"),
- ?line {ok, #file_info{type = regular}} = Mod:read_link_info("nisse�"),
- ?line ok = Mod:delete("nisse�"),
- ?line ok = Mod:make_link("fil1",treat_icky(<<"nisse�">>)),
- ?line {ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisse�">>)),
- ?line {ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisse�">>)),
- ?line ok = Mod:delete(treat_icky(<<"nisse�">>)),
+ ?line ok = Mod:make_link("fil1","nisseö"),
+ ?line {ok, <<"fil1">>} = Mod:read_file("nisseö"),
+ ?line {ok, #file_info{type = regular}} = Mod:read_link_info("nisseö"),
+ ?line ok = Mod:delete("nisseö"),
+ ?line ok = Mod:make_link("fil1",treat_icky(<<"nisseö">>)),
+ ?line {ok, <<"fil1">>} = Mod:read_file(treat_icky(<<"nisseö">>)),
+ ?line {ok, #file_info{type = regular}} = Mod:read_link_info(treat_icky(<<"nisseö">>)),
+ ?line ok = Mod:delete(treat_icky(<<"nisseö">>)),
?line {ok, <<"fil1">>} = Mod:read_file("fil1"),
- ?line {error,enoent} = Mod:read_file("nisse�"),
- ?line {error,enoent} = Mod:read_link_info("nisse�"),
- ?line {error,enoent} = Mod:read_file(treat_icky(<<"nisse�">>)),
- ?line {error,enoent} = Mod:read_link_info(treat_icky(<<"nisse�">>));
+ ?line {error,enoent} = Mod:read_file("nisseö"),
+ ?line {error,enoent} = Mod:read_link_info("nisseö"),
+ ?line {error,enoent} = Mod:read_file(treat_icky(<<"nisseö">>)),
+ ?line {error,enoent} = Mod:read_link_info(treat_icky(<<"nisseö">>));
false ->
ok
end,
@@ -430,42 +431,42 @@ check_icky(Mod) ->
?line {ok, BC} = Mod:read(FD,1024),
?line ok = file:close(FD)
end || {regular,Name,Content} <- icky_dir() ],
- ?line Mod:rename("���2","���_fil1"),
- ?line {ok, <<"���2">>} = Mod:read_file("���_fil1"),
- ?line {error,enoent} = Mod:read_file("���2"),
- ?line Mod:rename("���_fil1","���2"),
- ?line {ok, <<"���2">>} = Mod:read_file("���2"),
- ?line {error,enoent} = Mod:read_file("���_fil1"),
+ ?line Mod:rename("åäö2","åäö_fil1"),
+ ?line {ok, <<"åäö2">>} = Mod:read_file("åäö_fil1"),
+ ?line {error,enoent} = Mod:read_file("åäö2"),
+ ?line Mod:rename("åäö_fil1","åäö2"),
+ ?line {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
+ ?line {error,enoent} = Mod:read_file("åäö_fil1"),
- ?line Mod:rename("���2",treat_icky(<<"���_fil1">>)),
- ?line {ok, <<"���2">>} = Mod:read_file(treat_icky(<<"���_fil1">>)),
+ ?line Mod:rename("åäö2",treat_icky(<<"åäö_fil1">>)),
+ ?line {ok, <<"åäö2">>} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
if
UniMode and (OS =/= win32) ->
- {error,enoent} = Mod:read_file("���_fil1");
+ {error,enoent} = Mod:read_file("åäö_fil1");
true ->
ok
end,
- ?line {error,enoent} = Mod:read_file("���2"),
- ?line Mod:rename(treat_icky(<<"���_fil1">>),"���2"),
- ?line {ok, <<"���2">>} = Mod:read_file("���2"),
- ?line {error,enoent} = Mod:read_file("���_fil1"),
- ?line {error,enoent} = Mod:read_file(treat_icky(<<"���_fil1">>)),
+ ?line {error,enoent} = Mod:read_file("åäö2"),
+ ?line Mod:rename(treat_icky(<<"åäö_fil1">>),"åäö2"),
+ ?line {ok, <<"åäö2">>} = Mod:read_file("åäö2"),
+ ?line {error,enoent} = Mod:read_file("åäö_fil1"),
+ ?line {error,enoent} = Mod:read_file(treat_icky(<<"åäö_fil1">>)),
- ?line {ok,FI} = Mod:read_file_info("���2"),
+ ?line {ok,FI} = Mod:read_file_info("åäö2"),
?line NewMode = FI#file_info.mode band (bnot 8#333),
?line NewMode2 = NewMode bor 8#222,
?line true = NewMode2 =/= NewMode,
- ?line ok = Mod:write_file_info("���2",FI#file_info{mode = NewMode}),
- ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info("���2"),
- ?line ok = Mod:write_file_info("���2",FI#file_info{mode = NewMode2}),
- ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("���2"),
+ ?line ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode}),
+ ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info("åäö2"),
+ ?line ok = Mod:write_file_info("åäö2",FI#file_info{mode = NewMode2}),
+ ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info("åäö2"),
- ?line {ok,FII} = Mod:read_file_info(treat_icky(<<"���5">>)),
+ ?line {ok,FII} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
?line true = NewMode2 =/= NewMode,
- ?line ok = Mod:write_file_info(treat_icky(<<"���5">>),FII#file_info{mode = NewMode}),
- ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"���5">>)),
- ?line ok = Mod:write_file_info(<<"���5">>,FII#file_info{mode = NewMode2}),
- ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"���5">>)),
+ ?line ok = Mod:write_file_info(treat_icky(<<"åäö5">>),FII#file_info{mode = NewMode}),
+ ?line {ok,#file_info{mode = NewMode}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
+ ?line ok = Mod:write_file_info(<<"åäö5">>,FII#file_info{mode = NewMode2}),
+ ?line {ok,#file_info{mode = NewMode2}} = Mod:read_file_info(treat_icky(<<"åäö5">>)),
ok
after
Mod:set_cwd(Dir),
@@ -475,7 +476,7 @@ check_icky(Mod) ->
check_very_icky(Mod) ->
{ok,Dir} = Mod:get_cwd(),
try
- ?line true=(length("���") =:= 3),
+ ?line true=(length("åäö") =:= 3),
?line UniMode = file:native_name_encoding() =/= latin1,
if
not UniMode ->
@@ -497,7 +498,7 @@ check_very_icky(Mod) ->
?line chk_cre_dir(Mod,[{directory,[1088,1079,1091]++"_dir",very_icky_dir()}]),
?line {ok,BeginAt} = Mod:get_cwd(),
?line true = is_list(BeginAt),
- ?line {error,enoent} = Mod:set_cwd("��_dir"),
+ ?line {error,enoent} = Mod:set_cwd("åä_dir"),
?line ok = Mod:set_cwd([1088,1079,1091]++"_dir"),
?line {ok, NowAt} = Mod:get_cwd(),
?line true = is_list(NowAt),
@@ -514,16 +515,16 @@ check_very_icky(Mod) ->
?line {ok, #file_info{type = regular}} =
Mod:read_link_info("nisse"++[1088,1079,1091]),
?line ok = Mod:delete("nisse"++[1088,1079,1091]),
- ?line ok = Mod:make_link("fil1",<<"nisse�">>),
- ?line {ok, <<"fil1">>} = Mod:read_file(<<"nisse�">>),
+ ?line ok = Mod:make_link("fil1",<<"nisseö">>),
+ ?line {ok, <<"fil1">>} = Mod:read_file(<<"nisseö">>),
?line {ok, #file_info{type = regular}} =
- Mod:read_link_info(<<"nisse�">>),
- ?line ok = Mod:delete(<<"nisse�">>),
+ Mod:read_link_info(<<"nisseö">>),
+ ?line ok = Mod:delete(<<"nisseö">>),
?line {ok, <<"fil1">>} = Mod:read_file("fil1"),
?line {error,enoent} = Mod:read_file("nisse"++[1088,1079,1091]),
?line {error,enoent} = Mod:read_link_info("nisse"++[1088,1079,1091]),
- ?line {error,enoent} = Mod:read_file(<<"nisse�">>),
- ?line {error,enoent} = Mod:read_link_info(<<"nisse�">>);
+ ?line {error,enoent} = Mod:read_file(<<"nisseö">>),
+ ?line {error,enoent} = Mod:read_link_info(<<"nisseö">>);
false ->
ok
end,
@@ -540,10 +541,10 @@ check_very_icky(Mod) ->
end || {regular,Name,Content} <- very_icky_dir() ],
?line Mod:rename([956,965,963,954,959,49],
[956,965,963,954,959]++"_fil1"),
- ?line {ok, <<"���2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"),
+ ?line {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"),
?line {error,enoent} = Mod:read_file([956,965,963,954,959,49]),
?line Mod:rename([956,965,963,954,959]++"_fil1",[956,965,963,954,959,49]),
- ?line {ok, <<"���2">>} = Mod:read_file([956,965,963,954,959,49]),
+ ?line {ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959,49]),
?line {error,enoent} = Mod:read_file([956,965,963,954,959]++"_fil1"),
?line {ok,FI} = Mod:read_file_info([956,965,963,954,959,49]),
@@ -574,9 +575,9 @@ check_very_icky(Mod) ->
end,
?line {NumOK,NumNOK} = filelib:fold_files(".",".*",true,fun(_F,{N,M}) when is_list(_F) -> io:format("~ts~n",[_F]),{N+1,M}; (_F,{N,M}) -> io:format("~p~n",[_F]),{N,M+1} end,{0,0}),
?line ok = filelib:fold_files(".",[1076,1089,1072,124,46,42],true,fun(_F,_) -> ok end,false),
- ?line SF3 = unicode:characters_to_binary("���subfil3",
+ ?line SF3 = unicode:characters_to_binary("åäösubfil3",
file:native_name_encoding()),
- ?line SF2 = case treat_icky(<<"���subfil2">>) of
+ ?line SF2 = case treat_icky(<<"åäösubfil2">>) of
LF2 when is_list(LF2) ->
unicode:characters_to_binary(LF2,
file:native_name_encoding());
@@ -584,7 +585,7 @@ check_very_icky(Mod) ->
BF2
end,
?line Sorted = lists:sort([SF3,SF2]),
- ?line Sorted = lists:sort(filelib:wildcard("*",<<"���subdir2">>)),
+ ?line Sorted = lists:sort(filelib:wildcard("*",<<"åäösubdir2">>)),
ok
catch
throw:need_unicode_mode ->
@@ -744,26 +745,26 @@ hopeless_darwin() ->
icky_dir() ->
[{regular,"fil1","fil1"},
- {regular,"���2","���2"}] ++
+ {regular,"åäö2","åäö2"}] ++
case has_links() of
true ->
- [{regular,"���3","���2"},
- {symlink,"���4","���2"}];
+ [{regular,"åäö3","åäö2"},
+ {symlink,"åäö4","åäö2"}];
false ->
[]
end ++
- [{regular,treat_icky(<<"���5">>),"���5"}] ++
+ [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
case has_links() of
true ->
- [{symlink,treat_icky(<<"���6">>),treat_icky(<<"���5">>)}];
+ [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
false ->
[]
end ++
- [{directory,treat_icky(<<"���subdir2">>),
- [{regular,treat_icky(<<"���subfil2">>),"���subfil12"},
- {regular,"���subfil3","���subfil13"}]},
- {directory,"���subdir",
- [{regular,"���subfil1","���subfil1"}]}].
+ [{directory,treat_icky(<<"åäösubdir2">>),
+ [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
+ {regular,"åäösubfil3","åäösubfil13"}]},
+ {directory,"åäösubdir",
+ [{regular,"åäösubfil1","åäösubfil1"}]}].
make_very_icky_dir(Mod) ->
rm_rf(Mod,"very_icky_dir"),
@@ -774,26 +775,26 @@ make_very_icky_dir(Mod) ->
very_icky_dir() ->
[{regular,"fil1","fil1"},
- {regular,[956,965,963,954,959,49],"���2"}] ++
+ {regular,[956,965,963,954,959,49],"åäö2"}] ++
case has_links() of
true ->
- [{regular,[956,965,963,954,959,50],"���2"},
+ [{regular,[956,965,963,954,959,50],"åäö2"},
{symlink,[956,965,963,954,959,51],[956,965,963,954,959,49]}];
false ->
[]
end ++
- [{regular,treat_icky(<<"���5">>),"���5"}] ++
+ [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
case has_links() of
true ->
- [{symlink,treat_icky(<<"���6">>),treat_icky(<<"���5">>)}];
+ [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
false ->
[]
end ++
- [{directory,treat_icky(<<"���subdir2">>),
- [{regular,treat_icky(<<"���subfil2">>),"���subfil12"},
- {regular,"���subfil3","���subfil13"}]},
+ [{directory,treat_icky(<<"åäösubdir2">>),
+ [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
+ {regular,"åäösubfil3","åäösubfil13"}]},
{directory,[956,965,963,954,959]++"subdir1",
- [{regular,[956,965,963,954,959]++"subfil1","���subfil1"}]}].
+ [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}].
%% Some OS'es simply do not allow non UTF8 filenames
treat_icky(Bin) ->
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index 2354f8accd..cd768813cf 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -442,7 +443,7 @@ open_fd(suite) ->
open_fd(doc) ->
["Test that the 'fd' option works"];
open_fd(Config) when is_list(Config) ->
- Msg = "Det g�r ont n�r knoppar brista. Varf�r skulle annars v�ren tveka?",
+ Msg = "Det gör ont när knoppar brista. Varför skulle annars våren tveka?",
Addr = {127,0,0,1},
{ok,S1} = gen_udp:open(0),
{ok,P2} = inet:port(S1),
diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index 2ec3b7c297..320b23bea1 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -83,10 +83,10 @@ init_per_suite(Config) when is_list(Config) ->
{win32, windows} ->
{skipped, "No use to run on Windows 95/98"};
_ ->
- Config
+ ignore_cores:init(Config)
end.
end_per_suite(Config) when is_list(Config) ->
- Config.
+ ignore_cores:fini(Config).
start_check(Type, Name) ->
@@ -188,8 +188,20 @@ reboot(Config) when is_list(Config) ->
%% Check that a node is up and running after a crash.
%% 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
+%% for crash dumps
node_start_immediately_after_crash(suite) -> {req, [{time, 10}]};
node_start_immediately_after_crash(Config) when is_list(Config) ->
+ Config2 = ignore_cores:setup(?MODULE, node_start_immediately_after_crash, Config, true),
+ try
+ node_start_immediately_after_crash_test(Config2)
+ after
+ ignore_cores:restore(Config2)
+ end.
+
+
+node_start_immediately_after_crash_test(Config) when is_list(Config) ->
{ok, Node} = start_check(loose, heart_test_imm, [{"ERL_CRASH_DUMP_SECONDS", "0"}]),
ok = rpc:call(Node, heart, set_cmd,
@@ -228,8 +240,19 @@ node_start_immediately_after_crash(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(suite) -> {req, [{time, 10}]};
node_start_soon_after_crash(Config) when is_list(Config) ->
+ Config2 = ignore_cores:setup(?MODULE, node_start_soon_after_crash, Config, true),
+ try
+ node_start_soon_after_crash_test(Config2)
+ after
+ ignore_cores:restore(Config2)
+ end.
+
+node_start_soon_after_crash_test(Config) when is_list(Config) ->
{ok, Node} = start_check(loose, heart_test_soon, [{"ERL_CRASH_DUMP_SECONDS", "10"}]),
ok = rpc:call(Node, heart, set_cmd,
diff --git a/lib/kernel/test/ignore_cores.erl b/lib/kernel/test/ignore_cores.erl
new file mode 100644
index 0000000000..8b1ac0fe6c
--- /dev/null
+++ b/lib/kernel/test/ignore_cores.erl
@@ -0,0 +1,158 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : ignore_cores.erl
+%%% Author : Rickard Green <[email protected]>
+%%% Description :
+%%%
+%%% Created : 11 Feb 2008 by Rickard Green <[email protected]>
+%%%-------------------------------------------------------------------
+
+-module(ignore_cores).
+
+-include_lib("test_server/include/test_server.hrl").
+
+-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]).
+
+-record(ignore_cores, {org_cwd,
+ org_path,
+ org_pwd_env,
+ ign_dir = false,
+ cores_dir = false}).
+
+%%
+%% Takes a testcase config
+%%
+
+init(Config) ->
+ {ok, OrgCWD} = file:get_cwd(),
+ [{ignore_cores,
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = code:get_path(),
+ org_pwd_env = os:getenv("PWD")}}
+ | lists:keydelete(ignore_cores, 1, Config)].
+
+fini(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ ok = file:set_cwd(OrgCWD),
+ true = code:set_path(OrgPath),
+ case OrgPWD of
+ false -> ok;
+ _ -> true = os:putenv("PWD", OrgPWD)
+ end,
+ lists:keydelete(ignore_cores, 1, Config).
+
+setup(Suite, Testcase, Config) ->
+ setup(Suite, Testcase, Config, false).
+
+setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite),
+ is_atom(Testcase),
+ is_list(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath),
+ true = code:set_path(Path),
+ PrivDir = ?config(priv_dir, Config),
+ IgnDir = filename:join([PrivDir,
+ atom_to_list(Suite)
+ ++ "_"
+ ++ atom_to_list(Testcase)
+ ++ "_wd"]),
+ ok = file:make_dir(IgnDir),
+ case SetCwd of
+ false ->
+ ok;
+ _ ->
+ ok = file:set_cwd(IgnDir),
+ OrgPWD = case os:getenv("PWD") of
+ false -> false;
+ PWD ->
+ os:putenv("PWD", IgnDir),
+ PWD
+ end
+ end,
+ ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>),
+ %% cores are dumped in /cores on MacOS X
+ CoresDir = case {?t:os_type(), filelib:is_dir("/cores")} of
+ {{unix,darwin}, true} ->
+ filelib:fold_files("/cores",
+ "^core.*$",
+ false,
+ fun (C,Cs) -> [C|Cs] end,
+ []);
+ _ ->
+ false
+ end,
+ lists:keyreplace(ignore_cores,
+ 1,
+ Config,
+ {ignore_cores,
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD,
+ ign_dir = IgnDir,
+ cores_dir = CoresDir}}).
+
+restore(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD,
+ ign_dir = IgnDir,
+ cores_dir = CoresDir} = ?config(ignore_cores, Config),
+ try
+ case CoresDir of
+ false ->
+ ok;
+ _ ->
+ %% Move cores dumped by these testcases in /cores
+ %% to cwd.
+ lists:foreach(fun (C) ->
+ case lists:member(C, CoresDir) of
+ true -> ok;
+ _ ->
+ Dst = filename:join(
+ [IgnDir,
+ filename:basename(C)]),
+ {ok, _} = file:copy(C, Dst),
+ file:delete(C)
+ end
+ end,
+ filelib:fold_files("/cores",
+ "^core.*$",
+ false,
+ fun (C,Cs) -> [C|Cs] end,
+ []))
+ end
+ after
+ catch file:set_cwd(OrgCWD),
+ catch code:set_path(OrgPath),
+ case OrgPWD of
+ false -> ok;
+ _ -> catch os:putenv("PWD", OrgPWD)
+ end
+ end.
+
+
+dir(Config) ->
+ #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config),
+ Dir.
diff --git a/lib/kernel/test/ram_file_SUITE.erl b/lib/kernel/test/ram_file_SUITE.erl
index ab95a3ff5f..5c4437d4d3 100644
--- a/lib/kernel/test/ram_file_SUITE.erl
+++ b/lib/kernel/test/ram_file_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -167,7 +168,7 @@ pread_pwrite(suite) ->
pread_pwrite(doc) ->
["Test that pread/2,3 and pwrite/2,3 works."];
pread_pwrite(Config) when is_list(Config) ->
- ?line Str = "Flygande b�ckaziner s�ka hwila p� mjuqa tuvor x",
+ ?line Str = "Flygande bäckaziner söka hwila på mjuqa tuvor x",
?line Bin = list_to_binary(Str),
%%
pread_pwrite_test(?FILE_MODULE, Str, [ram, read, write]),
@@ -206,7 +207,7 @@ position(suite) ->
position(doc) ->
["Test that position/2 works."];
position(Config) when is_list(Config) ->
- ?line Str = "Att vara eller icke vara, det �r fr�gan. ",
+ ?line Str = "Att vara eller icke vara, det är frågan. ",
?line Bin = list_to_binary(Str),
%%
position_test(?FILE_MODULE, Str, [ram, read]),
@@ -287,8 +288,8 @@ truncate(suite) ->
truncate(doc) ->
["Test that truncate/1 works."];
truncate(Config) when is_list(Config) ->
- ?line Str = "M�n �dlare att lida och f�rdraga "
- ++ "ett bittert �des stygn av pilar, ",
+ ?line Str = "Mån ädlare att lida och fördraga "
+ ++ "ett bittert ödes stygn av pilar, ",
?line Bin = list_to_binary(Str),
%%
ok = truncate_test(?FILE_MODULE, Str, [ram, read, write]),
@@ -331,7 +332,7 @@ sync(suite) ->
sync(doc) ->
["Test that sync/1 at least does not crash."];
sync(Config) when is_list(Config) ->
- ?line Str = "�n att ta till vapen mot ett hav av kval. ",
+ ?line Str = "än att ta till vapen mot ett hav av kval. ",
?line Bin = list_to_binary(Str),
%%
sync_test(?FILE_MODULE, Str, [ram, read, write]),
@@ -365,8 +366,8 @@ get_set_file(doc) ->
["Tests get_file/1, set_file/2, get_file_close/1 and get_size/1."];
get_set_file(Config) when is_list(Config) ->
%% These two strings should not be of equal length.
- ?line Str = "N�r h�gan nord blir sn�bet�ckt, ",
- ?line Str2 = "f�r alla harar byta dr�kt. ",
+ ?line Str = "När högan nord blir snöbetäckt, ",
+ ?line Str2 = "får alla harar byta dräkt. ",
?line Bin = list_to_binary(Str),
?line Bin2 = list_to_binary(Str2),
%%
diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3a.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3a.erl
index 72b3112053..24dc410dbe 100644
--- a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3a.erl
+++ b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3a.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -204,7 +204,7 @@ decode_name(_Config, Scope, Item) ->
%% to command requests from the MGC that audit
%% ObservedEventsDescriptor, and found in the
%% ObservedEventsDescriptor. See 12.2. If there are no parameters
-%% for the ObservedEvents Descriptor, then �none� shall be specified.
+%% for the ObservedEvents Descriptor, then 'none' shall be specified.
%%
%%
%% 12.1.4 Signals
@@ -225,7 +225,7 @@ decode_name(_Config, Scope, Item) ->
%%
%% BR (Brief)
%%
-%% NOTE -�SignalType may be defined such that it is dependent on
+%% NOTE - SignalType may be defined such that it is dependent on
%% the value of one or more parameters. The package MUST specify a
%% default signal type. If the default type is TO, the package MUST
%% specify a default duration which may be provisioned. A default
diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3b.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3b.erl
index 12e673ac81..d89717c00a 100644
--- a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3b.erl
+++ b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3b.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -204,7 +204,7 @@ decode_name(_Config, Scope, Item) ->
%% to command requests from the MGC that audit
%% ObservedEventsDescriptor, and found in the
%% ObservedEventsDescriptor. See 12.2. If there are no parameters
-%% for the ObservedEvents Descriptor, then �none� shall be specified.
+%% for the ObservedEvents Descriptor, then 'none' shall be specified.
%%
%%
%% 12.1.4 Signals
@@ -225,7 +225,7 @@ decode_name(_Config, Scope, Item) ->
%%
%% BR (Brief)
%%
-%% NOTE -�SignalType may be defined such that it is dependent on
+%% NOTE - SignalType may be defined such that it is dependent on
%% the value of one or more parameters. The package MUST specify a
%% default signal type. If the default type is TO, the package MUST
%% specify a default duration which may be provisioned. A default
diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3c.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3c.erl
index d08231caac..8b4192ad44 100644
--- a/lib/megaco/src/binary/megaco_binary_name_resolver_prev3c.erl
+++ b/lib/megaco/src/binary/megaco_binary_name_resolver_prev3c.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -204,7 +204,7 @@ decode_name(_Config, Scope, Item) ->
%% to command requests from the MGC that audit
%% ObservedEventsDescriptor, and found in the
%% ObservedEventsDescriptor. See 12.2. If there are no parameters
-%% for the ObservedEvents Descriptor, then �none� shall be specified.
+%% for the ObservedEvents Descriptor, then 'none' shall be specified.
%%
%%
%% 12.1.4 Signals
@@ -225,7 +225,7 @@ decode_name(_Config, Scope, Item) ->
%%
%% BR (Brief)
%%
-%% NOTE -�SignalType may be defined such that it is dependent on
+%% NOTE - SignalType may be defined such that it is dependent on
%% the value of one or more parameters. The package MUST specify a
%% default signal type. If the default type is TO, the package MUST
%% specify a default duration which may be provisioned. A default
diff --git a/lib/megaco/src/binary/megaco_binary_name_resolver_v3.erl b/lib/megaco/src/binary/megaco_binary_name_resolver_v3.erl
index c101aa15bc..20954d4c9d 100644
--- a/lib/megaco/src/binary/megaco_binary_name_resolver_v3.erl
+++ b/lib/megaco/src/binary/megaco_binary_name_resolver_v3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -204,7 +204,7 @@ decode_name(_Config, Scope, Item) ->
%% to command requests from the MGC that audit
%% ObservedEventsDescriptor, and found in the
%% ObservedEventsDescriptor. See 12.2. If there are no parameters
-%% for the ObservedEvents Descriptor, then �none� shall be specified.
+%% for the ObservedEvents Descriptor, then 'none' shall be specified.
%%
%%
%% 12.1.4 Signals
@@ -225,7 +225,7 @@ decode_name(_Config, Scope, Item) ->
%%
%% BR (Brief)
%%
-%% NOTE -�SignalType may be defined such that it is dependent on
+%% NOTE - SignalType may be defined such that it is dependent on
%% the value of one or more parameters. The package MUST specify a
%% default signal type. If the default type is TO, the package MUST
%% specify a default duration which may be provisioned. A default
diff --git a/lib/megaco/test/megaco_codec_prev3a_test.erl b/lib/megaco/test/megaco_codec_prev3a_test.erl
index 4f1160b93f..b2316eb509 100644
--- a/lib/megaco/test/megaco_codec_prev3a_test.erl
+++ b/lib/megaco/test/megaco_codec_prev3a_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -3104,7 +3104,7 @@ pretty_otp5068_msg1() ->
190,
asn1_NOVALUE,
{actionReplies,
- [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger
+ [{'ActionReply', %% Comments: This is repeated many times.
0,
asn1_NOVALUE,
asn1_NOVALUE,
diff --git a/lib/megaco/test/megaco_codec_prev3b_test.erl b/lib/megaco/test/megaco_codec_prev3b_test.erl
index 4bd49365e7..fa24f49372 100644
--- a/lib/megaco/test/megaco_codec_prev3b_test.erl
+++ b/lib/megaco/test/megaco_codec_prev3b_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -3223,7 +3223,7 @@ pretty_otp5068_msg1() ->
190,
asn1_NOVALUE,
{actionReplies,
- [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger
+ [{'ActionReply', %% Comments: This is repeated many times.
0,
asn1_NOVALUE,
asn1_NOVALUE,
diff --git a/lib/megaco/test/megaco_codec_prev3c_test.erl b/lib/megaco/test/megaco_codec_prev3c_test.erl
index baa1c7f547..7f6d098ed8 100644
--- a/lib/megaco/test/megaco_codec_prev3c_test.erl
+++ b/lib/megaco/test/megaco_codec_prev3c_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -2679,7 +2679,7 @@ pretty_otp5068_msg1() ->
190,
asn1_NOVALUE,
{actionReplies,
- [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger
+ [{'ActionReply', %% Comments: This is repeated many times.
0,
asn1_NOVALUE,
asn1_NOVALUE,
diff --git a/lib/megaco/test/megaco_codec_v1_test.erl b/lib/megaco/test/megaco_codec_v1_test.erl
index 86f332fde0..3be0da3ae4 100644
--- a/lib/megaco/test/megaco_codec_v1_test.erl
+++ b/lib/megaco/test/megaco_codec_v1_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -3298,7 +3298,7 @@ pretty_otp5068_msg1() ->
190,
asn1_NOVALUE,
{actionReplies,
- [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger
+ [{'ActionReply', %% Comments: This is repeated many times.
0,
asn1_NOVALUE,
asn1_NOVALUE,
diff --git a/lib/megaco/test/megaco_codec_v2_test.erl b/lib/megaco/test/megaco_codec_v2_test.erl
index e8db9e1cb1..1f522504d6 100644
--- a/lib/megaco/test/megaco_codec_v2_test.erl
+++ b/lib/megaco/test/megaco_codec_v2_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -3722,7 +3722,7 @@ pretty_otp5068_msg1() ->
190,
asn1_NOVALUE,
{actionReplies,
- [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger
+ [{'ActionReply', %% Comments: This is repeated many times.
0,
asn1_NOVALUE,
asn1_NOVALUE,
diff --git a/lib/megaco/test/megaco_codec_v3_test.erl b/lib/megaco/test/megaco_codec_v3_test.erl
index 67805479f9..9d564a0ae3 100644
--- a/lib/megaco/test/megaco_codec_v3_test.erl
+++ b/lib/megaco/test/megaco_codec_v3_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -2701,7 +2701,7 @@ pretty_otp5068_msg1() ->
190,
asn1_NOVALUE,
{actionReplies,
- [{'ActionReply', %% Comments: Detta upprepas m�nga g�nger
+ [{'ActionReply', %% Comments: This is repeated many times.
0,
asn1_NOVALUE,
asn1_NOVALUE,
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index a22c95d454..14011003d3 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -1177,9 +1177,9 @@ system_code_change(State, _Module, _OldVsn, _Extra) ->
%% AXD301 patch sort pids according to R9B sort order
%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Om R9B == true, g�rs j�mf�relsen som i R9B plain.
-%% Om R9B == false, g�rs j�mf�relsen som i alla andra releaser.
-%% cmp_tid(T1, T2) returnerar -1 om T1 < T2, 0 om T1 = T2 och 1 om T1 > T2.
+%% Om R9B == true, the comparison is done as in R9B plain.
+%% Om R9B == false, the comparison is done as in any other release.
+%% cmp_tid(T1, T2) returns -1 if T1 < T2, 0 if T1 = T2 and 1 if T1 > T2.
-define(VERSION_MAGIC, 131).
-define(ATOM_EXT, 100).
diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl
index 6f882d0be9..4c04126d4f 100644
--- a/lib/observer/test/crashdump_viewer_SUITE.erl
+++ b/lib/observer/test/crashdump_viewer_SUITE.erl
@@ -34,6 +34,7 @@
-define(default_timeout, ?t:minutes(30)).
-define(sl_alloc_vsns,[r9b]).
+-define(failed_file,"failed-cases.txt").
init_per_testcase(_Case, Config) ->
DataDir = ?config(data_dir,Config),
@@ -42,9 +43,18 @@ init_per_testcase(_Case, Config) ->
catch crashdump_viewer:stop(),
Dog = ?t:timetrap(?default_timeout),
[{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
+end_per_testcase(Case, Config) ->
Dog=?config(watchdog, Config),
?t:timetrap_cancel(Dog),
+ case ?config(tc_status,Config) of
+ ok ->
+ ok;
+ _Fail ->
+ File = filename:join(?config(data_dir,Config),?failed_file),
+ {ok,Fd}=file:open(File,[append]),
+ file:write(Fd,io_lib:format("~w.~n",[Case])),
+ file:close(Fd)
+ end,
ok.
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -67,15 +77,26 @@ init_per_suite(doc) ->
["Create a lot of crashdumps which can be used in the testcases below"];
init_per_suite(Config) when is_list(Config) ->
Dog = ?t:timetrap(?default_timeout),
+ delete_saved(Config),
application:start(inets), % will be using the http client later
httpc:set_options([{ipfamily,inet6fb4}]),
DataDir = ?config(data_dir,Config),
- Rels = [R || R <- [r13b,r14b], ?t:is_release_available(R)] ++ [current],
+ Rels = [R || R <- [r14b,r15b], ?t:is_release_available(R)] ++ [current],
io:format("Creating crash dumps for the following releases: ~p", [Rels]),
AllDumps = create_dumps(DataDir,Rels),
?t:timetrap_cancel(Dog),
[{dumps,AllDumps}|Config].
+delete_saved(Config) ->
+ DataDir = ?config(data_dir,Config),
+ file:delete(filename:join(DataDir,?failed_file)),
+ SaveDir = filename:join(DataDir,"save"),
+ Dumps = filelib:wildcard(filename:join(SaveDir,"*")),
+ lists:foreach(fun(F) -> file:delete(F) end, Dumps),
+ file:del_dir(SaveDir),
+ ok.
+
+
translate(suite) ->
[];
translate(doc) ->
@@ -196,6 +217,23 @@ end_per_suite(doc) ->
["Remove generated crashdumps"];
end_per_suite(Config) when is_list(Config) ->
Dumps = ?config(dumps,Config),
+ DataDir = ?config(data_dir,Config),
+ FailedFile = filename:join(DataDir,?failed_file),
+ case filelib:is_file(FailedFile) of
+ true ->
+ SaveDir = filename:join(DataDir,"save"),
+ file:make_dir(SaveDir),
+ file:copy(FailedFile,filename:join(SaveDir,?failed_file)),
+ lists:foreach(
+ fun(CD) ->
+ File = filename:basename(CD),
+ New = filename:join(SaveDir,File),
+ file:copy(CD,New)
+ end, Dumps);
+ false ->
+ ok
+ end,
+ file:delete(FailedFile),
lists:foreach(fun(CD) -> ok = file:delete(CD) end,Dumps),
lists:keydelete(dumps,1,Config).
@@ -388,7 +426,7 @@ special(Port,File) ->
%% I registered a process as aaaaaaaa in the full_dist dumps
%% to make sure it will be the first in the list when sorted
- %% on names. There are some special data here, s� I'll thoroughly
+ %% on names. There are some special data here, so I'll thoroughly
%% read the process details for this process. Other processes
%% are just briefly traversed.
{Pid,Rest1} = get_first_process(AllProcs),
@@ -568,11 +606,14 @@ expand_link(Html) ->
port_details(Port) ->
- Port1 = contents(Port,"port?port=Port<0.1>"),
- "#Port<0.1>" = title(Port1),
-
Port0 = contents(Port,"port?port=Port<0.0>"),
- "Could not find port: #Port<0.0>" = title(Port0).
+ Port1 = contents(Port,"port?port=Port<0.1>"),
+ case title(Port0) of
+ "#Port<0.0>" -> % R16 or later
+ "Could not find port: #Port<0.1>" = title(Port1);
+ "Could not find port: #Port<0.0>" -> % R15 or earlier
+ "#Port<0.1>" = title(Port1)
+ end.
is_truncated(File) ->
case filename:extension(filename:rootname(File)) of
@@ -691,6 +732,12 @@ dump_with_strange_module_name(DataDir,Rel,DumpName) ->
CD.
dump(Node,DataDir,Rel,DumpName) ->
+ case Rel of
+ _ when Rel<r15b, Rel=/=current ->
+ rpc:call(Node,os,putenv,["ERL_CRASH_DUMP_SECONDS","600"]);
+ _ ->
+ ok
+ end,
rpc:call(Node,erlang,halt,[DumpName]),
Crashdump0 = filename:join(filename:dirname(code:which(?t)),
"erl_crash_dump.n1"),
@@ -752,6 +799,7 @@ rel_opt(Rel) ->
r12b -> [{erl,[{release,"r12b_patched"}]}];
r13b -> [{erl,[{release,"r13b_patched"}]}];
r14b -> [{erl,[{release,"r14b_latest"}]}]; %naming convention changed
+ r15b -> [{erl,[{release,"r15b_latest"}]}];
current -> []
end.
@@ -764,7 +812,8 @@ dump_prefix(Rel) ->
r12b -> "r12b_dump.";
r13b -> "r13b_dump.";
r14b -> "r14b_dump.";
- current -> "r15b_dump."
+ r15b -> "r15b_dump.";
+ current -> "r16b_dump."
end.
compat_rel(Rel) ->
@@ -776,5 +825,6 @@ compat_rel(Rel) ->
r12b -> "+R12 ";
r13b -> "+R13 ";
r14b -> "+R14 ";
+ r15b -> "+R15 ";
current -> ""
end.
diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml
index 0e3386b11f..a984bf4485 100644
--- a/lib/odbc/doc/src/odbc.xml
+++ b/lib/odbc/doc/src/odbc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2011</year>
+ <year>1999</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -105,8 +105,14 @@
odbc_data_type() = sql_integer | sql_smallint | sql_tinyint |
{sql_decimal, precision(), scale()} |
{sql_numeric, precision(), scale()} |
- {sql_char, size()} | {sql_wchar, size()} | {sql_varchar, size()} | {sql_wvarchar, size()}| {sql_float, precision()} |
- {sql_wlongvarchar, size()} | {sql_float, precision()} | sql_real | sql_double | sql_bit | atom()
+ {sql_char, size()} |
+ {sql_wchar, size()} |
+ {sql_varchar, size()} |
+ {sql_wvarchar, size()}|
+ {sql_float, precision()} |
+ {sql_wlongvarchar, size()} |
+ {sql_float, precision()} |
+ sql_real | sql_double | sql_bit | atom()
</code>
<code type="none">
precision() = integer() </code>
diff --git a/lib/odbc/test/odbc_data_type_SUITE.erl b/lib/odbc/test/odbc_data_type_SUITE.erl
index d61a91f973..2d33546622 100644
--- a/lib/odbc/test/odbc_data_type_SUITE.erl
+++ b/lib/odbc/test/odbc_data_type_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1469,7 +1470,7 @@ utf8(Config) when is_list(Config) ->
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++ "(FIELD text)"),
- Latin1Data = ["���������",
+ Latin1Data = ["ÖÄÅÄÖÅäöå",
"testasdf",
"Row 3",
"Row 4",
@@ -1564,7 +1565,7 @@ timestamp(Config) when is_list(Config) ->
%%------------------------------------------------------------------------
w_char_support(Ref, Table, CharType, Size) ->
- Latin1Data = ["���������",
+ Latin1Data = ["ÖÄÅÄÖÅäöå",
"testasdf",
"Row 3",
"Row 4",
diff --git a/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml b/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml
index 964ae3e92d..1fd2f644cb 100644
--- a/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml
+++ b/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2010</year>
+ <year>1997</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1142,7 +1142,8 @@ handle_info(_Info, State) ->
module, and <c>lookup</c> in <c>DB_Administrator_impl.erl</c><em>and</em><c>DB_CommonUser_impl.erl</c>. But wait, is that really necessary? Actually,
it is not. We simple use the IC compile option <em>impl</em>:</p>
<pre>
-$ <input>erlc +'{{impl, "DB::CommonUser"}, "DBUser_impl"}' +'{{impl, "DB::Administrator"}, "DBUser_impl"}' DB.idl</input>
+$ <input>erlc +'{{impl, "DB::CommonUser"}, "DBUser_impl"}'\
+ +'{{impl, "DB::Administrator"}, "DBUser_impl"}' DB.idl</input>
$ <input>erlc *.erl</input>
</pre>
<p>Instead of creating, and not the least, maintaining two call-back modules,
diff --git a/lib/orber/src/orber_iiop_net.erl b/lib/orber/src/orber_iiop_net.erl
index 2eed0b538a..33e02e3c04 100644
--- a/lib/orber/src/orber_iiop_net.erl
+++ b/lib/orber/src/orber_iiop_net.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -415,11 +415,10 @@ handle_info({'EXIT', Pid, _Reason}, State) when is_pid(Pid) ->
ref = Ref, options = Options, proxy_options = POpts}] ->
ets:delete(?CONNECTION_DB, Pid),
unlink(Pid),
- NewListen = new_listen_socket(Type, Listen, Port, Options),
- {ok, NewPid} = orber_iiop_socketsup:start_accept(Type, NewListen,
+ {ok, NewPid} = orber_iiop_socketsup:start_accept(Type, Listen,
Ref, POpts),
link(NewPid),
- ets:insert(?CONNECTION_DB, #listen{pid = NewPid, socket = NewListen,
+ ets:insert(?CONNECTION_DB, #listen{pid = NewPid, socket = Listen,
port = Port, type = Type,
ref = Ref, options = Options,
proxy_options = POpts}),
@@ -445,23 +444,6 @@ handle_info({'EXIT', Pid, _Reason}, State) when is_pid(Pid) ->
handle_info(_, State) ->
{noreply, State}.
-new_listen_socket(normal, ListenFd, _Port, _Options) ->
- ListenFd;
-new_listen_socket(ssl, ListenFd, Port, Options) ->
- Generation = orber_env:ssl_generation(),
- if
- Generation > 2 ->
- ListenFd;
- true ->
- case is_process_alive(ssl:pid(ListenFd)) of
- true ->
- ListenFd;
- _ ->
- {ok, Listen, _NP} = orber_socket:listen(ssl, Port, Options, true),
- Listen
- end
- end.
-
from_list(List) ->
from_list(List, queue:new()).
diff --git a/lib/os_mon/src/os_mon.erl b/lib/os_mon/src/os_mon.erl
index df1eccb064..19acae9f0e 100644
--- a/lib/os_mon/src/os_mon.erl
+++ b/lib/os_mon/src/os_mon.erl
@@ -176,9 +176,7 @@ services({unix, sunos}) ->
services({unix, _}) -> % Other unix.
[cpu_sup, disksup, memsup];
services({win32, _}) ->
- [disksup, memsup, os_sup, sysinfo];
-services(_) ->
- [].
+ [disksup, memsup, os_sup, sysinfo].
server_name(cpu_sup) -> cpu_sup;
server_name(disksup) -> disksup;
diff --git a/lib/parsetools/include/yeccpre.hrl b/lib/parsetools/include/yeccpre.hrl
index 3672394fc5..e4c3ba52be 100644
--- a/lib/parsetools/include/yeccpre.hrl
+++ b/lib/parsetools/include/yeccpre.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -36,7 +36,7 @@ parse_and_scan({M, F, A}) ->
-spec format_error(any()) -> [char() | list()].
format_error(Message) ->
- case io_lib:deep_char_list(Message) of
+ case io_lib:deep_unicode_char_list(Message) of
true ->
Message;
_ ->
@@ -164,7 +164,7 @@ yecctoken_location(Token) ->
yecctoken2string({atom, _, A}) -> io_lib:write(A);
yecctoken2string({integer,_,N}) -> io_lib:write(N);
yecctoken2string({float,_,F}) -> io_lib:write(F);
-yecctoken2string({char,_,C}) -> io_lib:write_char(C);
+yecctoken2string({char,_,C}) -> io_lib:write_unicode_char(C);
yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
yecctoken2string({string,_,S}) -> io_lib:write_unicode_string(S);
yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A);
diff --git a/lib/parsetools/src/esyntax.yrl b/lib/parsetools/src/esyntax.yrl
deleted file mode 100644
index 1ecb54f0a7..0000000000
--- a/lib/parsetools/src/esyntax.yrl
+++ /dev/null
@@ -1,360 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-Nonterminals
-add_op attribute basic_type bif_test
-case_expr clause_body
-clause_guard clause_head comp_op cr_clause cr_clauses expr expr_tail
-exprs farity farity_list form formal_parameter_list function
-function_call function_clause guard guard_call guard_expr
-guard_expr_list guard_exprs guard_expr_tail guard_expr_tuple
-guard_parameter_list
-guard_tests guard_test if_clause if_clauses if_expr list match_expr
-mult_op parameter_list pattern patterns pattern_list pattern_tail pattern_tuple
-prefix_op receive_expr send_expr tuple.
-
-Terminals
-'!' '(' ')' '*' '+' ',' '-' '->' '/' '/=' ':' ';' '<' '=' '=/=' '=:='
-'=<' '==' '>' '>=' '[' ']' 'after' 'band' 'begin' 'bnot'
-'bor' 'bsl' 'bsr' 'bxor' 'case' 'catch' 'div' 'end' 'if' 'of'
-'receive' 'rem' 'when' '{' '|' '}' atom float integer string var.
-% 'receive' 'rem' 'true' 'when' '{' '|' '}' atom float integer string var.
-
-Rootsymbol form.
-
-Endsymbol dot.
-
-Unary 0 'catch'.
-Right 200 '='.
-Right 200 '!'.
-Left 300 add_op.
-Left 400 mult_op.
-Unary 500 prefix_op.
-
-
-add_op -> '+' : '$1'.
-add_op -> '-' : '$1'.
-add_op -> 'bor' : '$1'.
-add_op -> 'bxor' : '$1'.
-add_op -> 'bsl' : '$1'.
-add_op -> 'bsr' : '$1'.
-
-comp_op -> '==' : '$1'.
-comp_op -> '/=' : '$1'.
-comp_op -> '=<' : '$1'.
-comp_op -> '<' : '$1'.
-comp_op -> '>=' : '$1'.
-comp_op -> '>' : '$1'.
-comp_op -> '=:=' : '$1'.
-comp_op -> '=/=' : '$1'.
-
-mult_op -> '*' : '$1'.
-mult_op -> '/' : '$1'.
-mult_op -> 'div' : '$1'.
-mult_op -> 'rem' : '$1'.
-mult_op -> 'band' : '$1'.
-
-prefix_op -> '+' : '$1'.
-prefix_op -> '-' : '$1'.
-prefix_op -> 'bnot' : '$1'.
-
-
-basic_type -> atom : '$1'.
-basic_type -> float : '$1'.
-basic_type -> integer : '$1'.
-basic_type -> string : '$1'.
-basic_type -> var : '$1'.
-% basic_type -> 'true' : {atom, element(2, '$1'), 'true'}.
-
-
-pattern -> basic_type : '$1'.
-pattern -> pattern_list : '$1'.
-pattern -> pattern_tuple : '$1'.
-
-pattern_list -> '[' ']' : {nil, element(2, '$1')}.
-pattern_list -> '[' pattern pattern_tail ']' :
- {cons, element(2, '$1'), '$2', '$3'}.
-
-pattern_tail -> '|' pattern : '$2'.
-pattern_tail -> ',' pattern pattern_tail :
- {cons, element(2, '$2'), '$2', '$3'}.
-pattern_tail -> '$empty' : {nil, 0}.
-
-pattern_tuple -> '{' '}' : {tuple, element(2, '$1'), []}.
-pattern_tuple -> '{' patterns '}' : {tuple, element(2, '$1'), '$2'}.
-
-patterns -> pattern : ['$1'].
-patterns -> pattern ',' patterns : ['$1' | '$3'].
-
-
-expr -> basic_type : '$1'.
-expr -> list : '$1'.
-expr -> tuple : '$1'.
-expr -> function_call : '$1'.
-
-expr -> expr add_op expr :
- {Op, Pos} = '$2',
- {arith, Pos, Op, '$1', '$3'}.
-expr -> expr mult_op expr :
- {Op, Pos} = '$2',
- {arith, Pos, Op, '$1', '$3'}.
-expr -> prefix_op expr:
- case '$2' of
- {float, Pos, N} ->
- case '$1' of
- {'-', _} ->
- {float, Pos, -N};
- {'+', _} ->
- {float, Pos, N};
- {Op, Pos1} ->
- {arith, Pos1, Op, {float, Pos, N}}
- end;
- {integer, Pos, N} ->
- case '$1' of
- {'-', _} ->
- {integer, Pos, -N};
- {'+', _} ->
- {integer, Pos, N};
- {Op, Pos1} ->
- {arith, Pos1, Op, {integer, Pos, N}}
- end;
- _ ->
- {Op, Pos} = '$1',
- {arith, Pos, Op, '$2'}
- end.
-
-expr -> '(' expr ')' : '$2'.
-expr -> 'begin' exprs 'end' : {block, element(2, '$1'), '$2'}.
-expr -> 'catch' expr : {'catch', element(2, '$1'), '$2'}.
-
-expr -> case_expr : '$1'.
-expr -> if_expr : '$1'.
-expr -> receive_expr : '$1'.
-expr -> match_expr : '$1'.
-expr -> send_expr : '$1'.
-
-
-list -> '[' ']' : {nil, element(2, '$1')}.
-list -> '[' expr expr_tail ']' : {cons, element(2, '$1'), '$2', '$3'}.
-
-expr_tail -> '|' expr : '$2'.
-expr_tail -> ',' expr expr_tail : {cons, element(2, '$2'), '$2', '$3'}.
-expr_tail -> '$empty' : {nil, 0}.
-
-tuple -> '{' '}' : {tuple, element(2, '$1'), []}.
-tuple -> '{' exprs '}' : {tuple, element(2, '$1'), '$2'}.
-
-
-function_call -> atom '(' parameter_list ')' :
- case erl_parse:erlang_bif(element(3, '$1'), length('$3')) of
- true ->
- {bif, element(2, '$1'), element(3, '$1'), '$3'};
- false ->
- {call, element(2, '$1'), [], element(3, '$1'), '$3'}
- end.
-function_call -> atom ':' atom '(' parameter_list ')' :
- {call, element(2, '$1'), element(3, '$1'), element(3, '$3'), '$5'}.
-
-parameter_list -> exprs : '$1'.
-parameter_list -> '$empty' : [].
-
-
-case_expr -> 'case' expr 'of' cr_clauses 'end' :
- {'case', element(2, '$1'), '$2', '$4'}.
-
-cr_clause -> pattern clause_guard clause_body :
- {clause, element(2, '$1'), ['$1'], '$2', '$3'}.
-
-cr_clauses -> cr_clause : ['$1'].
-cr_clauses -> cr_clause ';' cr_clauses : ['$1' | '$3'].
-
-if_expr -> 'if' if_clauses 'end' : {'if', element(2, '$1'), '$2'}.
-
-if_clause -> guard clause_body : {clause, element(2, hd('$2')), '$1', '$2'}.
-
-if_clauses -> if_clause : ['$1'].
-if_clauses -> if_clause ';' if_clauses : ['$1' | '$3'].
-
-receive_expr -> 'receive' 'after' expr clause_body 'end' :
- {'receive', element(2, '$1'), [], '$3', '$4'}.
-receive_expr -> 'receive' cr_clauses 'end' :
- {'receive', element(2, '$1'), '$2'}.
-receive_expr -> 'receive' cr_clauses 'after' expr clause_body 'end' :
- {'receive', element(2, '$1'), '$2', '$4', '$5'}.
-
-
-match_expr -> expr '=' expr :
- case erl_parse:is_term('$1') of
- true ->
- {match, element(2, '$1'), '$1', '$3'};
- false ->
- throw({error, {element(2, '$1'), yecc, "illegal lhs in match **"}})
- end.
-
-send_expr -> expr '!' expr :
- Pos = element(2, '$1'),
- {send, Pos, '$1', '$3'}.
-
-
-exprs -> expr : ['$1'].
-exprs -> expr ',' exprs : ['$1' | '$3'].
-
-
-guard_expr -> basic_type : '$1'.
-guard_expr -> guard_expr_list : '$1'.
-guard_expr -> guard_expr_tuple : '$1'.
-guard_expr -> guard_call : '$1'.
-guard_expr -> '(' guard_expr ')' : '$2'.
-guard_expr -> guard_expr add_op guard_expr :
- {Op, Pos} = '$2',
- {arith, Pos, Op, '$1', '$3'}.
-guard_expr -> guard_expr mult_op guard_expr :
- {Op, Pos} = '$2',
- {arith, Pos, Op, '$1', '$3'}.
-guard_expr -> prefix_op guard_expr:
- case '$2' of
- {float, Pos, N} ->
- case '$1' of
- {'-', _} ->
- {float, Pos, -N};
- {'+', _} ->
- {float, Pos, N};
- {Op, Pos1} ->
- {arith, Pos1, Op, {float, Pos, N}}
- end;
- {integer, Pos, N} ->
- case '$1' of
- {'-', _} ->
- {integer, Pos, -N};
- {'+', _} ->
- {integer, Pos, N};
- {Op, Pos1} ->
- {arith, Pos1, Op, {integer, Pos, N}}
- end;
- _ ->
- {Op, Pos} = '$1',
- {arith, Pos, Op, '$2'}
- end.
-
-guard_expr_list -> '[' ']' : {nil, element(2, '$1')}.
-guard_expr_list -> '[' guard_expr guard_expr_tail ']' :
- {cons, element(2, '$1'), '$2', '$3'}.
-
-guard_expr_tail -> '|' guard_expr : '$2'.
-guard_expr_tail -> ',' guard_expr guard_expr_tail :
- {cons, element(2, '$2'), '$2', '$3'}.
-guard_expr_tail -> '$empty' : {nil, 0}.
-
-guard_expr_tuple -> '{' '}' : {tuple, element(2, '$1'), []}.
-guard_expr_tuple -> '{' guard_exprs '}' : {tuple, element(2, '$1'), '$2'}.
-
-guard_exprs -> guard_expr : ['$1'].
-guard_exprs -> guard_expr ',' guard_exprs : ['$1' | '$3'].
-
-
-guard_call -> atom '(' guard_parameter_list ')' :
- case erl_parse:erlang_guard_bif(element(3, '$1'), length('$3')) of
- true ->
- {bif, element(2, '$1'), element(3, '$1'), '$3'};
- false ->
- throw({error, {element(2, '$1'), yecc, "illegal test in guard **"}})
- end.
-
-guard_parameter_list -> guard_exprs : '$1'.
-guard_parameter_list -> '$empty' : [].
-
-
-bif_test -> atom '(' guard_parameter_list ')' :
- case erl_parse:erlang_guard_test(element(3, '$1'), length('$3')) of
- true ->
- {test, element(2, '$1'), element(3, '$1'), '$3'};
- false ->
- throw({error, {element(2, '$1'), yecc, "illegal test in guard **"}})
- end.
-
-
-guard_test -> bif_test : '$1'.
-guard_test -> guard_expr comp_op guard_expr :
- {Op, Pos} = '$2',
- {comp, Pos, Op, '$1', '$3'}.
-
-guard_tests -> guard_test : ['$1'].
-guard_tests -> guard_test ',' guard_tests : ['$1' | '$3'].
-
-% guard -> 'true' : [].
-guard -> atom :
- case '$1' of
- {atom, _, true} ->
- [];
- _ ->
- throw({error, {element(2, '$1'), yecc, "illegal test in guard **"}})
- end.
-guard -> guard_tests : '$1'.
-
-
-function_clause -> clause_head clause_guard clause_body :
- {Name, Line, Arity, Parameters} = '$1',
- {function, Line, Name, Arity,
- [{clause, element(2, hd('$3')), Parameters, '$2', '$3'}]}.
-
-clause_head -> atom '(' formal_parameter_list ')' :
- {element(3, '$1'), element(2, '$1'), length('$3'), '$3'}.
-
-formal_parameter_list -> patterns : '$1'.
-formal_parameter_list -> '$empty' : [].
-
-clause_guard -> 'when' guard : '$2'.
-clause_guard -> '$empty' : [].
-
-clause_body -> '->' exprs: '$2'.
-
-
-function -> function_clause : '$1'.
-function -> function_clause ';' function :
- case '$1' of
- {function, Pos1, Name1, Arity1, [Clause]} ->
- case '$3' of
- {function, _, Name1, Arity2, Clauses} ->
- if
- Arity1 /= Arity2 ->
- throw({error, {Pos1, yecc,
- io_lib:format('arity conflict in definition of ~w',
- [Name1])}});
- true ->
- {function, Pos1, Name1, Arity1, [Clause | Clauses]}
- end;
- _ ->
- throw({error, {Pos1, yecc,
- io_lib:format('missing final dot in def of ~w/~w',
- [Name1, Arity1])}})
- end
- end.
-
-
-attribute -> atom : element(3, '$1').
-attribute -> '[' farity_list ']' : '$2'.
-
-farity_list -> farity : ['$1'].
-farity_list -> farity ',' farity_list : ['$1' | '$3'].
-
-farity -> atom '/' integer : {element(3, '$1'), element(3, '$3')}.
-
-
-form -> '-' atom '(' attribute ')' :
- {attribute, element(2, '$2'), element(3, '$2'), '$4'}.
-form -> function : '$1'.
diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl
index cdf20461d9..bbef4053b4 100644
--- a/lib/parsetools/src/leex.erl
+++ b/lib/parsetools/src/leex.erl
@@ -58,6 +58,7 @@
gfile=[], % Graph file
module, % Module name
opts=[], % Options
+ encoding=none, % Encoding of Xrl file
% posix=false, % POSIX regular expressions
errors=[],
warnings=[]
@@ -146,7 +147,9 @@ format_error({regexp,E})->
end,
["bad regexp `",Es,"'"];
format_error(ignored_characters) ->
- "ignored characters".
+ "ignored characters";
+format_error(cannot_parse) ->
+ io_lib:fwrite("cannot parse; probably encoding mismatch", []).
%%%
%%% Local functions
@@ -298,10 +301,10 @@ pack_warnings([]) ->
report_errors(St) ->
when_opt(fun () ->
foreach(fun({File,{none,Mod,E}}) ->
- io:fwrite("~s: ~s\n",
+ io:fwrite("~s: ~ts\n",
[File,Mod:format_error(E)]);
({File,{Line,Mod,E}}) ->
- io:fwrite("~s:~w: ~s\n",
+ io:fwrite("~s:~w: ~ts\n",
[File,Line,Mod:format_error(E)])
end, sort(St#leex.errors))
end, report_errors, St#leex.opts).
@@ -316,11 +319,11 @@ report_warnings(St) ->
ShouldReport = member(report_warnings, St#leex.opts) orelse ReportWerror,
when_bool(fun () ->
foreach(fun({File,{none,Mod,W}}) ->
- io:fwrite("~s: ~s~s\n",
+ io:fwrite("~s: ~s~ts\n",
[File,Prefix,
Mod:format_error(W)]);
({File,{Line,Mod,W}}) ->
- io:fwrite("~s:~w: ~s~s\n",
+ io:fwrite("~s:~w: ~s~ts\n",
[File,Line,Prefix,
Mod:format_error(W)])
end, sort(St#leex.warnings))
@@ -396,17 +399,18 @@ verbose_print(St, Format, Args) ->
parse_file(St0) ->
case file:open(St0#leex.xfile, [read]) of
{ok,Xfile} ->
+ St1 = St0#leex{encoding = epp:set_encoding(Xfile)},
try
- verbose_print(St0, "Parsing file ~s, ", [St0#leex.xfile]),
+ verbose_print(St1, "Parsing file ~s, ", [St1#leex.xfile]),
%% We KNOW that errors throw so we can ignore them here.
- {ok,Line1,St1} = parse_head(Xfile, St0),
- {ok,Line2,Macs,St2} = parse_defs(Xfile, Line1, St1),
- {ok,Line3,REAs,Actions,St3} =
- parse_rules(Xfile, Line2, Macs, St2),
- {ok,Code,St4} = parse_code(Xfile, Line3, St3),
- verbose_print(St1, "contained ~w rules.~n", [length(REAs)]),
- {ok,REAs,Actions,Code,St4}
- after file:close(Xfile)
+ {ok,Line1,St2} = parse_head(Xfile, St1),
+ {ok,Line2,Macs,St3} = parse_defs(Xfile, Line1, St2),
+ {ok,Line3,REAs,Actions,St4} =
+ parse_rules(Xfile, Line2, Macs, St3),
+ {ok,Code,St5} = parse_code(Xfile, Line3, St4),
+ verbose_print(St5, "contained ~w rules.~n", [length(REAs)]),
+ {ok,REAs,Actions,Code,St5}
+ after ok = file:close(Xfile)
end;
{error,Error} ->
add_error({none,leex,{file_error,Error}}, St0)
@@ -415,7 +419,7 @@ parse_file(St0) ->
%% parse_head(File, State) -> {ok,NextLine,State}.
%% Parse the head of the file. Skip all comments and blank lines.
-parse_head(Ifile, St) -> {ok,nextline(Ifile, 0),St}.
+parse_head(Ifile, St) -> {ok,nextline(Ifile, 0, St),St}.
%% parse_defs(File, Line, State) -> {ok,NextLine,Macros,State}.
%% Parse the macro definition section of a file. This must exist.
@@ -423,7 +427,7 @@ parse_head(Ifile, St) -> {ok,nextline(Ifile, 0),St}.
parse_defs(Ifile, {ok,?DEFS_HEAD ++ Rest,L}, St) ->
St1 = warn_ignored_chars(L, Rest, St),
- parse_defs(Ifile, nextline(Ifile, L), [], St1);
+ parse_defs(Ifile, nextline(Ifile, L, St), [], St1);
parse_defs(_, {ok,_,L}, St) ->
add_error({L,leex,missing_defs}, St);
parse_defs(_, {eof,L}, St) ->
@@ -435,7 +439,7 @@ parse_defs(Ifile, {ok,Chars,L}=Line, Ms, St) ->
case re:run(Chars, MS, [{capture,all_but_first,list}]) of
{match,[Name,Def]} ->
%%io:fwrite("~p = ~p\n", [Name,Def]),
- parse_defs(Ifile, nextline(Ifile, L), [{Name,Def}|Ms], St);
+ parse_defs(Ifile, nextline(Ifile, L, St), [{Name,Def}|Ms], St);
_ -> {ok,Line,Ms,St} % Anything else
end;
parse_defs(_, Line, Ms, St) ->
@@ -446,7 +450,7 @@ parse_defs(_, Line, Ms, St) ->
parse_rules(Ifile, {ok,?RULE_HEAD ++ Rest,L}, Ms, St) ->
St1 = warn_ignored_chars(L, Rest, St),
- parse_rules(Ifile, nextline(Ifile, L), Ms, [], [], 0, St1);
+ parse_rules(Ifile, nextline(Ifile, L, St), Ms, [], [], 0, St1);
parse_rules(_, {ok,_,L}, _, St) ->
add_error({L,leex,missing_rules}, St);
parse_rules(_, {eof,L}, _, St) ->
@@ -464,7 +468,7 @@ parse_rules(Ifile, NextLine, Ms, REAs, As, N, St) ->
case collect_rule(Ifile, Chars, L0) of
{ok,Re,Atoks,L1} ->
{ok,REA,A,St1} = parse_rule(Re, L0, Atoks, Ms, N, St),
- parse_rules(Ifile, nextline(Ifile, L1), Ms,
+ parse_rules(Ifile, nextline(Ifile, L1, St), Ms,
[REA|REAs], [A|As], N+1, St1);
{error,E} -> add_error(E, St)
end;
@@ -497,8 +501,10 @@ collect_rule(Ifile, Chars, L0) ->
{error,E,_} -> {error,E}
end.
+collect_action(_Ifile, {error, _}, L, _Cont0) ->
+ {error, {L, leex, cannot_parse}, ignored_end_line};
collect_action(Ifile, Chars, L0, Cont0) ->
- case erl_scan:tokens(Cont0, Chars, L0) of
+ case erl_scan:tokens(Cont0, Chars, L0, [unicode]) of
{done,{ok,Toks,_},_} -> {ok,Toks,L0};
{done,{eof,_},_} -> {eof,L0};
{done,{error,E,_},_} -> {error,E,L0};
@@ -560,29 +566,32 @@ parse_code(Ifile, {ok,?CODE_HEAD ++ Rest,CodeL}, St) ->
St1 = warn_ignored_chars(CodeL, Rest, St),
{ok, CodePos} = file:position(Ifile, cur),
%% Just count the lines; copy the code from file to file later.
- NCodeLines = count_lines(Ifile, 0),
+ EndCodeLine = count_lines(Ifile, CodeL, St),
+ NCodeLines = EndCodeLine - CodeL,
{ok,{CodeL,CodePos,NCodeLines},St1};
parse_code(_, {ok,_,L}, St) ->
add_error({L,leex,missing_code}, St);
parse_code(_, {eof,L}, St) ->
add_error({L,leex,missing_code}, St).
-count_lines(File, N) ->
+count_lines(File, N, St) ->
case io:get_line(File, leex) of
eof -> N;
- _Line -> count_lines(File, N+1)
+ {error, _} -> add_error({N+1, leex, cannot_parse}, St);
+ _Line -> count_lines(File, N+1, St)
end.
-%% nextline(InputFile, PrevLineNo) -> {ok,Chars,LineNo} | {eof,LineNo}.
+%% nextline(InputFile, PrevLineNo, State) -> {ok,Chars,LineNo} | {eof,LineNo}.
%% Get the next line skipping comment lines and blank lines.
-nextline(Ifile, L) ->
+nextline(Ifile, L, St) ->
case io:get_line(Ifile, leex) of
eof -> {eof,L};
+ {error, _} -> add_error({L+1, leex, cannot_parse}, St);
Chars ->
case substr(Chars, span(Chars, " \t\n")+1) of
- [$%|_Rest] -> nextline(Ifile, L+1);
- [] -> nextline(Ifile, L+1);
+ [$%|_Rest] -> nextline(Ifile, L+1, St);
+ [] -> nextline(Ifile, L+1, St);
_Other -> {ok,Chars,L+1}
end
end.
@@ -1289,19 +1298,21 @@ out_file(St0, DFA, DF, Actions, Code) ->
try
case file:open(St0#leex.efile, [write]) of
{ok,Ofile} ->
+ set_encoding(St0, Ofile),
try
+ output_encoding_comment(Ofile, St0),
output_file_directive(Ofile, St0#leex.ifile, 0),
out_file(Ifile, Ofile, St0, DFA, DF, Actions,
Code, 1),
verbose_print(St0, "ok~n", []),
St0
- after file:close(Ofile)
+ after ok = file:close(Ofile)
end;
{error,Error} ->
verbose_print(St0, "error~n", []),
add_error({none,leex,{file_error,Error}}, St0)
end
- after file:close(Ifile)
+ after ok = file:close(Ifile)
end;
{{error,Error},Ifile} ->
add_error(Ifile, {none,leex,{file_error,Error}}, St0)
@@ -1310,7 +1321,9 @@ out_file(St0, DFA, DF, Actions, Code) ->
open_inc_file(State) ->
Ifile = State#leex.ifile,
case file:open(Ifile, [read]) of
- {ok,F} -> {ok,F};
+ {ok,F} ->
+ _ = epp:set_encoding(F),
+ {ok,F};
Error -> {Error,Ifile}
end.
@@ -1328,6 +1341,7 @@ inc_file_name(Filename) ->
out_file(Ifile, Ofile, St, DFA, DF, Actions, Code, L) ->
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);
Line ->
case substr(Line, 1, 5) of
"##mod" -> out_module(Ofile, St);
@@ -1347,14 +1361,23 @@ out_erlang_code(File, St, Code, L) ->
output_file_directive(File, St#leex.xfile, CodeL),
{ok,Xfile} = file:open(St#leex.xfile, [read]),
try
+ set_encoding(St, Xfile),
{ok,_} = file:position(Xfile, CodePos),
- {ok,_} = file:copy(Xfile, File)
+ ok = file_copy(Xfile, File)
after
- file:close(Xfile)
+ ok = file:close(Xfile)
end,
io:nl(File),
output_file_directive(File, St#leex.ifile, L).
+file_copy(From, To) ->
+ case io:get_line(From, leex) of
+ eof -> ok;
+ Line when is_list(Line) ->
+ io:fwrite(To, "~ts", [Line]),
+ file_copy(From, To)
+ end.
+
out_dfa(File, St, DFA, Code, DF, L) ->
{_CodeL,_CodePos,NCodeLines} = Code,
%% Three file attributes before this one...
@@ -1569,7 +1592,7 @@ out_dfa_graph(St, DFA, DF) ->
io:fwrite(Gfile, "}~n", []),
verbose_print(St, "ok~n", []),
St
- after file:close(Gfile)
+ after ok = file:close(Gfile)
end;
{error,Error} ->
verbose_print(St, "error~n", []),
@@ -1610,6 +1633,16 @@ dfa_edgelabel(Cranges) ->
(C) -> [quote(C)]
end, Cranges) ++ "]".
+set_encoding(#leex{encoding = none}, File) ->
+ ok = io:setopts(File, [{encoding, epp:default_encoding()}]);
+set_encoding(#leex{encoding = E}, File) ->
+ ok = io:setopts(File, [{encoding, E}]).
+
+output_encoding_comment(_File, #leex{encoding = none}) ->
+ ok;
+output_encoding_comment(File, #leex{encoding = Encoding}) ->
+ io:fwrite(File, <<"%% ~s\n">>, [epp:encoding_to_string(Encoding)]).
+
output_file_directive(File, Filename, Line) ->
io:fwrite(File, <<"-file(~s, ~w).\n">>,
[format_filename(Filename), Line]).
diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl
index b0792a6ed8..dbb7d025ae 100644
--- a/lib/parsetools/src/yecc.erl
+++ b/lib/parsetools/src/yecc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -42,6 +42,7 @@
includefile,
includefile_version,
module,
+ encoding = none,
options = [],
verbose = false,
file_attrs = true,
@@ -224,7 +225,11 @@ format_error({unused_nonterminal, Nonterminal}) ->
[format_symbol(Nonterminal)]);
format_error({unused_terminal, Terminal}) ->
io_lib:fwrite("terminal symbol ~s not used",
- [format_symbol(Terminal)]).
+ [format_symbol(Terminal)]);
+format_error({bad_symbol, String}) ->
+ io_lib:fwrite("bad symbol ~ts", [String]);
+format_error(cannot_parse) ->
+ io_lib:fwrite("cannot parse; possibly encoding mismatch", []).
file(File) ->
file(File, [report_errors, report_warnings]).
@@ -257,7 +262,7 @@ yecc(Infile, Outfile, Verbose) ->
yecc(Infile, Outfile, Verbose, []).
yecc(Infilex, Outfilex, Verbose, Includefilex) ->
- statistics(runtime),
+ _ = statistics(runtime),
case file(Infilex, [{parserfile, Outfilex},
{verbose, Verbose},
{report, true},
@@ -407,7 +412,9 @@ infile(Parent, Infilex, Options) ->
St = case file:open(St0#yecc.infile, [read, read_ahead]) of
{ok, Inport} ->
try
- outfile(St0#yecc{inport = Inport})
+ Encoding = epp:set_encoding(Inport),
+ St1 = St0#yecc{inport = Inport, encoding = Encoding},
+ outfile(St1)
after
ok = file:close(Inport)
end;
@@ -428,6 +435,8 @@ outfile(St0) ->
case file:open(St0#yecc.outfile, [write, delayed_write]) of
{ok, Outport} ->
try
+ %% Set the same encoding as infile:
+ set_encoding(St0, Outport),
generate(St0#yecc{outport = Outport, line = 1})
catch
throw: St1 ->
@@ -466,13 +475,14 @@ timeit(Name, Fun, St0) ->
-define(PASS(P), {P, fun P/1}).
generate(St0) ->
+ St1 = output_encoding_comment(St0),
Passes = [?PASS(parse_grammar), ?PASS(check_grammar),
?PASS(states_and_goto_table), ?PASS(parse_actions),
?PASS(action_conflicts), ?PASS(write_file)],
- F = case member(time, St0#yecc.options) of
+ F = case member(time, St1#yecc.options) of
true ->
io:fwrite(<<"Generating parser from grammar in ~s\n">>,
- [format_filename(St0#yecc.infile)]),
+ [format_filename(St1#yecc.infile)]),
fun timeit/3;
false ->
fun(_Name, Fn, St) -> Fn(St) end
@@ -484,13 +494,13 @@ generate(St0) ->
true -> throw(St2)
end
end,
- foldl(Fun, St0, Passes).
+ foldl(Fun, St1, Passes).
parse_grammar(St) ->
parse_grammar(St#yecc.inport, 1, St).
parse_grammar(Inport, Line, St) ->
- {NextLine, Grammar} = read_grammar(Inport, Line),
+ {NextLine, Grammar} = read_grammar(Inport, St, Line),
parse_grammar(Grammar, Inport, NextLine, St).
parse_grammar(eof, _Inport, _NextLine, St) ->
@@ -523,6 +533,8 @@ parse_grammar({rule, Rule, Tokens}, St0) ->
St#yecc{rules_list = [RuleDef | St#yecc.rules_list]};
parse_grammar({prec, Prec}, St) ->
St#yecc{prec = Prec ++ St#yecc.prec};
+parse_grammar({#symbol{}, [{string,Line,String}]}, St) ->
+ add_error(Line, {bad_symbol, String}, St);
parse_grammar({#symbol{line = Line, name = Name}, Symbols}, St) ->
CF = fun(I) ->
case element(I, St) of
@@ -543,12 +555,17 @@ parse_grammar({#symbol{line = Line, name = Name}, Symbols}, St) ->
_ -> add_warning(Line, bad_declaration, St)
end.
-read_grammar(Inport, Line) ->
+read_grammar(Inport, St, Line) ->
case yeccscan:scan(Inport, '', Line) of
{eof, NextLine} ->
{NextLine, eof};
{error, {ErrorLine, Mod, What}, NextLine} ->
{NextLine, {error, ErrorLine, {error, Mod, What}}};
+ {error, terminated} ->
+ throw(St);
+ {error, _} ->
+ File = St#yecc.infile,
+ throw(add_error(File, none, cannot_parse, St));
{ok, Input, NextLine} ->
{NextLine, case yeccparser:parse(Input) of
{error, {ErrorLine, Mod, Message}} ->
@@ -738,9 +755,9 @@ states_and_goto_table(St0) ->
create_precedence_table(St).
parse_actions(St) ->
- erase(), % the pd is used when decoding lookahead sets
+ _ = erase(), % the pd is used when decoding lookahead sets
ParseActions = compute_parse_actions(St#yecc.n_states, St, []),
- erase(),
+ _ = erase(),
St#yecc{parse_actions = ParseActions, state_tab = []}.
action_conflicts(St0) ->
@@ -841,10 +858,10 @@ report_errors(St) ->
case member(report_errors, St#yecc.options) of
true ->
foreach(fun({File,{none,Mod,E}}) ->
- io:fwrite(<<"~s: ~s\n">>,
+ io:fwrite(<<"~s: ~ts\n">>,
[File,Mod:format_error(E)]);
({File,{Line,Mod,E}}) ->
- io:fwrite(<<"~s:~w: ~s\n">>,
+ io:fwrite(<<"~s:~w: ~ts\n">>,
[File,Line,Mod:format_error(E)])
end, sort(St#yecc.errors));
false ->
@@ -861,11 +878,11 @@ report_warnings(St) ->
case member(report_warnings, St#yecc.options) orelse ReportWerror of
true ->
foreach(fun({File,{none,Mod,W}}) ->
- io:fwrite(<<"~s: ~s~s\n">>,
+ io:fwrite(<<"~s: ~s~ts\n">>,
[File,Prefix,
Mod:format_error(W)]);
({File,{Line,Mod,W}}) ->
- io:fwrite(<<"~s:~w: ~s~s\n">>,
+ io:fwrite(<<"~s:~w: ~s~ts\n">>,
[File,Line,Prefix,
Mod:format_error(W)])
end, sort(St#yecc.warnings));
@@ -1024,7 +1041,7 @@ compute_states(St0) ->
rp_info = RulePointerInfo,
goto = GotoTab},
- erase(),
+ _ = erase(),
EndsymCode = code_terminal(StC#yecc.endsymbol, StC#yecc.symbol_tab),
{StateId, State0} = compute_state([{EndsymCode, 1}], Tables),
@@ -1923,9 +1940,10 @@ output_prelude(Outport, Inport, St0) when St0#yecc.includefile =:= [] ->
{St20, 0, no_erlang_code};
Next_line ->
St_10 = output_file_directive(St20, Infile, Next_line-1),
- Nmbr_of_lines = include1([], Inport, Outport),
- {St_10, Nmbr_of_lines,
- {last_erlang_code_line, Next_line+Nmbr_of_lines}}
+ Last_line = include1([], Inport, Outport, Infile,
+ Next_line, St_10),
+ Nmbr_of_lines = Last_line - Next_line,
+ {St_10, Nmbr_of_lines, {last_erlang_code_line, Last_line}}
end,
St30 = nl(St25),
IncludeFile =
@@ -1946,13 +1964,13 @@ output_prelude(Outport, Inport, St0) ->
{St30, N_lines_1, no_erlang_code};
Next_line ->
St = output_file_directive(St30, Infile, Next_line-1),
- Nmbr_of_lines = include1([], Inport, Outport),
- {St, Nmbr_of_lines + N_lines_1,
- {last_erlang_code_line, Next_line+Nmbr_of_lines}}
+ Last_line = include1([], Inport, Outport, Infile, Next_line, St),
+ Nmbr_of_lines = Last_line - Next_line,
+ {St, Nmbr_of_lines + N_lines_1, {last_erlang_code_line, Last_line}}
end.
output_header(St0) ->
- lists:foldl(fun(Str, St) -> fwrite(St, <<"~s\n">>, [Str])
+ lists:foldl(fun(Str, St) -> fwrite(St, <<"~ts\n">>, [Str])
end, St0, St0#yecc.header).
output_goto(St, [{_Nonterminal, []} | Go], StateInfo) ->
@@ -2250,8 +2268,8 @@ output_inlined(St0, FunctionName, Reduce, Infile) ->
[append(["[", tl(A), " | __Stack]"])])
end,
St = St40#yecc{line = St40#yecc.line + NLines},
- fwrite(St, <<" [begin\n ~s\n end | ~s].\n\n">>,
- [pp_tokens(Tokens, Line0), Stack]).
+ fwrite(St, <<" [begin\n ~ts\n end | ~s].\n\n">>,
+ [pp_tokens(Tokens, Line0, St#yecc.encoding), Stack]).
inlined_function_name(State, "Cat") ->
inlined_function_name(State, "");
@@ -2421,24 +2439,24 @@ include(St, File, Outport) ->
{error, Reason} ->
throw(add_error(File, none, {file_error, Reason}, St));
{ok, Inport} ->
+ _ = epp:set_encoding(Inport),
Line = io:get_line(Inport, ''),
- N_lines = include1(Line, Inport, Outport),
- file:close(Inport),
- N_lines
+ try include1(Line, Inport, Outport, File, 1, St) - 1
+ after ok = file:close(Inport)
+ end
end.
-include1(Line, Inport, Outport) ->
- include1(Line, Inport, Outport, 0).
-
-include1(eof, _, _, Nmbr_of_lines) ->
- Nmbr_of_lines;
-include1(Line, Inport, Outport, Nmbr_of_lines) ->
+include1(eof, _, _, _File, L, _St) ->
+ L;
+include1({error, _}=_Error, _Inport, _Outport, File, L, St) ->
+ throw(add_error(File, L, cannot_parse, St));
+include1(Line, Inport, Outport, File, L, St) ->
Incr = case member($\n, Line) of
true -> 1;
false -> 0
end,
io:put_chars(Outport, Line),
- include1(io:get_line(Inport, ''), Inport, Outport, Nmbr_of_lines + Incr).
+ include1(io:get_line(Inport, ''), Inport, Outport, File, L + Incr, St).
includefile_version([]) ->
{1,4};
@@ -2465,18 +2483,22 @@ parse_file(Epp) ->
end.
%% Keeps the line breaks of the original code.
-pp_tokens(Tokens, Line0) ->
- concat(pp_tokens1(Tokens, Line0, [])).
+pp_tokens(Tokens, Line0, Enc) ->
+ concat(pp_tokens1(Tokens, Line0, Enc, [])).
-pp_tokens1([], _Line0, _T0) ->
+pp_tokens1([], _Line0, _Enc, _T0) ->
[];
-pp_tokens1([T | Ts], Line0, T0) ->
+pp_tokens1([T | Ts], Line0, Enc, T0) ->
Line = element(2, T),
- [pp_sep(Line, Line0, T0), pp_symbol(T) | pp_tokens1(Ts, Line, T)].
+ [pp_sep(Line, Line0, T0), pp_symbol(T, Enc)|pp_tokens1(Ts, Line, Enc, T)].
-pp_symbol({var,_,Var}) -> Var;
-pp_symbol({_,_,Symbol}) -> io_lib:fwrite(<<"~p">>, [Symbol]);
-pp_symbol({Symbol, _}) -> Symbol.
+pp_symbol({var,_,Var}, _Enc) -> Var;
+pp_symbol({string,_,String}, latin1) ->
+ io_lib:write_unicode_string_as_latin1(String);
+pp_symbol({string,_,String}, _Enc) -> io_lib:write_unicode_string(String);
+pp_symbol({_,_,Symbol}, latin1) -> io_lib:fwrite(<<"~p">>, [Symbol]);
+pp_symbol({_,_,Symbol}, _Enc) -> io_lib:fwrite(<<"~tp">>, [Symbol]);
+pp_symbol({Symbol, _}, _Enc) -> Symbol.
pp_sep(Line, Line0, T0) when Line > Line0 ->
["\n " | pp_sep(Line - 1, Line0, T0)];
@@ -2485,6 +2507,16 @@ pp_sep(_Line, _Line0, {'.',_}) ->
pp_sep(_Line, _Line0, _T0) ->
" ".
+set_encoding(#yecc{encoding = none}, Port) ->
+ ok = io:setopts(Port, [{encoding, epp:default_encoding()}]);
+set_encoding(#yecc{encoding = E}, Port) ->
+ ok = io:setopts(Port, [{encoding, E}]).
+
+output_encoding_comment(#yecc{encoding = none}=St) ->
+ St;
+output_encoding_comment(#yecc{encoding = Encoding}=St) ->
+ fwrite(St, <<"%% ~s\n">>, [epp:encoding_to_string(Encoding)]).
+
output_file_directive(St, Filename, Line) when St#yecc.file_attrs ->
fwrite(St, <<"-file(~s, ~w).\n">>,
[format_filename(Filename), Line]);
@@ -2529,7 +2561,7 @@ format_assoc(nonassoc) ->
format_symbol(Symbol) ->
String = concat([Symbol]),
- case erl_scan:string(String) of
+ case erl_scan:string(String, 1, [unicode]) of
{ok, [{atom, _, _}], _} ->
io_lib:fwrite(<<"~w">>, [Symbol]);
{ok, [{Word, _}], _} when Word =/= ':', Word =/= '->' ->
diff --git a/lib/parsetools/src/yeccscan.erl b/lib/parsetools/src/yeccscan.erl
index d7ec3ba8d3..9e0e85143a 100644
--- a/lib/parsetools/src/yeccscan.erl
+++ b/lib/parsetools/src/yeccscan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,7 +24,7 @@ scan(Inport) ->
scan(Inport, '', 1).
scan(Inport, Prompt, Line1) ->
- case catch io:scan_erl_form(Inport, Prompt, Line1) of
+ case catch io:scan_erl_form(Inport, Prompt, Line1, [unicode]) of
{eof, Line2} ->
{eof, Line2};
{ok, Tokens, Line2} ->
@@ -34,6 +34,8 @@ scan(Inport, Prompt, Line1) ->
_ ->
{ok, lex(Tokens), Line2}
end;
+ {error, Reason} ->
+ {error, Reason};
{error, Descriptor, Line2} ->
{error, Descriptor, Line2};
{'EXIT', Why} ->
diff --git a/lib/parsetools/test/leex_SUITE.erl b/lib/parsetools/test/leex_SUITE.erl
index 1e50aedf07..4a0f70ba71 100644
--- a/lib/parsetools/test/leex_SUITE.erl
+++ b/lib/parsetools/test/leex_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: latin-1 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -42,7 +43,9 @@
-export([
file/1, compile/1, syntax/1,
- pt/1, man/1, ex/1, ex2/1, not_yet/1]).
+ pt/1, man/1, ex/1, ex2/1, not_yet/1,
+
+ otp_10302/1]).
% Default timetrap timeout (set in init_per_testcase).
-define(default_timeout, ?t:minutes(1)).
@@ -63,7 +66,8 @@ all() ->
groups() ->
[{checks, [], [file, compile, syntax]},
- {examples, [], [pt, man, ex, ex2, not_yet]}].
+ {examples, [], [pt, man, ex, ex2, not_yet]},
+ {tickets, [], [otp_10302]}].
init_per_suite(Config) ->
Config.
@@ -875,6 +879,111 @@ not_yet(Config) when is_list(Config) ->
ok.
+otp_10302(doc) ->
+ "OTP-10302. Unicode characters scanner/parser.";
+otp_10302(suite) -> [];
+otp_10302(Config) when is_list(Config) ->
+ Dir = ?privdir,
+ Filename = filename:join(Dir, "file.xrl"),
+ Ret = [return, {report, true}],
+
+ ok = file:write_file(Filename,<<
+ "%% coding: UTF-8\n"
+ "�"
+ >>),
+ {error,[{_,[{2,leex,cannot_parse}]}],[]} =
+ leex:file(Filename, Ret),
+
+ ok = file:write_file(Filename,<<
+ "%% coding: UTF-8\n"
+ "Definitions.\n"
+ "�"
+ >>),
+ {error,[{_,[{3,leex,cannot_parse}]}],[]} = leex:file(Filename, Ret),
+
+ ok = file:write_file(Filename,<<
+ "%% coding: UTF-8\n"
+ "Definitions.\n"
+ "A = a\n"
+ "L = [{A}-{Z}]\n"
+ "Z = z\n"
+ "Rules.\n"
+ "{L}+ : {token,{list_to_atom(TokenChars),H�pp}}.\n"
+ >>),
+ {error,[{_,[{7,leex,cannot_parse}]}],[]} = leex:file(Filename, Ret),
+
+ ok = file:write_file(Filename,<<
+ "%% coding: UTF-8\n"
+ "Definitions.\n"
+ "A = a\n"
+ "L = [{A}-{Z}]\n"
+ "Z = z\n"
+ "Rules.\n"
+ "{L}+ : {token,{list_to_atom(TokenChars)}}.\n"
+ "Erlang code.\n"
+ "-export([t/0]).\n"
+ "t() ->\n"
+ " H�pp\n"
+ >>),
+ {error,[{_,[{11,leex,cannot_parse}]}],[]} = leex:file(Filename, Ret),
+
+ Mini = <<"Definitions.\n"
+ "D = [0-9]\n"
+ "Rules.\n"
+ "{L}+ : {token,{word,TokenLine,TokenChars}}.\n"
+ "Erlang code.\n">>,
+ LeexPre = filename:join(Dir, "leexinc.hrl"),
+ ?line ok = file:write_file(LeexPre, <<"%% coding: UTF-8\n �">>),
+ PreErrors = run_test(Config, Mini, LeexPre),
+ {error,[{IncludeFile,[{2,leex,cannot_parse}]}],[]} = PreErrors,
+ "leexinc.hrl" = filename:basename(IncludeFile),
+
+ Ts = [{uni_1,
+ <<"%% coding: UTF-8\n"
+ "Definitions.\n"
+ "A = a\n"
+ "L = [{A}-{Z}]\n"
+ "Z = z\n"
+ "Rules.\n"
+ "{L}+ : {token,{list_to_atom(TokenChars),\n"
+ "begin Häpp = foo, Häpp end,"
+ " 'Häpp',\"\\x{400}B\",\"örn_Ѐ\"}}.\n"
+ "Erlang code.\n"
+ "-export([t/0]).\n"
+ "t() ->\n"
+ " %% Häpp, 'Häpp',\"\\x{400}B\",\"örn_Ѐ\"\n"
+ " {ok, [R], 1} = string(\"tip\"),\n"
+ " {tip,foo,'Häpp',[1024,66],[246,114,110,95,1024]} = R,\n"
+ " Häpp = foo,\n"
+ " {tip, Häpp, 'Häpp',\"\\x{400}B\",\"örn_Ѐ\"} = R,\n"
+ " ok.\n">>,
+ default,
+ ok},
+ {uni_2,
+ <<"%% coding: Latin-1\n"
+ "Definitions.\n"
+ "A = a\n"
+ "L = [{A}-{Z}]\n"
+ "Z = z\n"
+ "Rules.\n"
+ "{L}+ : {token,{list_to_atom(TokenChars),\n"
+ "begin H�pp = foo, H�pp end,"
+ " 'H�pp',\"\\x{400}B\",\"örn_Ѐ\"}}.\n"
+ "Erlang code.\n"
+ "-export([t/0]).\n"
+ "t() ->\n"
+ " %% H�pp, 'H�pp',\"\\x{400}B\",\"örn_Ѐ\"\n"
+ " {ok, [R], 1} = string(\"tip\"),\n"
+ " {tip,foo,'H�pp',[1024,66],[195,182,114,110,95,208,128]} = R,\n"
+ " H�pp = foo,\n"
+ " {tip, H�pp, 'H�pp',\"\\x{400}B\",\"örn_Ѐ\"} = R,\n"
+ " ok.\n">>,
+ default,
+ ok}],
+ run(Config, Ts),
+
+ ok.
+
unwritable(Fname) ->
{ok, Info} = file:read_file_info(Fname),
Mode = Info#file_info.mode - 8#00200,
diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl
index 3d26adf1be..c306dbe833 100644
--- a/lib/parsetools/test/yecc_SUITE.erl
+++ b/lib/parsetools/test/yecc_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: latin-1 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -48,7 +49,7 @@
otp_5369/1, otp_6362/1, otp_7945/1, otp_8483/1, otp_8486/1,
- otp_7292/1, otp_7969/1, otp_8919/1]).
+ otp_7292/1, otp_7969/1, otp_8919/1, otp_10302/1]).
% Default timetrap timeout (set in init_per_testcase).
-define(default_timeout, ?t:minutes(1)).
@@ -75,7 +76,7 @@ groups() ->
[empty, prec, yeccpre, lalr, old_yecc, other_examples]},
{bugs, [],
[otp_5369, otp_6362, otp_7945, otp_8483, otp_8486]},
- {improvements, [], [otp_7292, otp_7969, otp_8919]}].
+ {improvements, [], [otp_7292, otp_7969, otp_8919, otp_10302]}].
init_per_suite(Config) ->
Config.
@@ -1815,6 +1816,153 @@ otp_8919(Config) when is_list(Config) ->
"syntax error before: \"hello\"" = lists:flatten(Mod:format_error(Mess)),
ok.
+otp_10302(doc) ->
+ "OTP-10302. Unicode characters scanner/parser.";
+otp_10302(suite) -> [];
+otp_10302(Config) when is_list(Config) ->
+ Dir = ?privdir,
+ Filename = filename:join(Dir, "OTP-10302.yrl"),
+ Ret = [return, {report, true}],
+ Mini1 = <<"%% coding: utf-8
+ Nonterminals H�pp.
+ nt -> t.">>,
+ ok = file:write_file(Filename, Mini1),
+ %% This could (and should) be refined:
+ {error,[{Filename,[{2,Mod1,Err1}]}],[]} =
+ yecc:file(Filename, Ret),
+ "cannot translate from UTF-8" = Mod1:format_error(Err1),
+
+ Mini2 = <<"%% coding: Utf-8
+ Nonterminals Hopp.
+ Terminals t.
+ Rootsymbol Hopp.
+
+ Hopp -> t.
+
+ Erlang code.
+
+ t() ->
+ H�pp.">>,
+ ok = file:write_file(Filename, Mini2),
+ {error,[{Filename,[{11,Mod2,Err2}]}],[]} =
+ yecc:file(Filename, Ret),
+ "cannot parse; possibly encoding mismatch" = Mod2:format_error(Err2),
+
+ Mini3 = <<"%% coding: latin-1
+ Nonterminals Hopp.
+ Terminals t.
+ Rootsymbol Hopp.
+
+ Hopp -> t.
+
+ Erlang code.
+
+ t() ->
+ H�pp.">>,
+ ok = file:write_file(Filename, Mini3),
+ YeccPre = filename:join(Dir, "yeccpre.hrl"),
+ ok = file:write_file(YeccPre, [<<"%% coding: UTF-8\n �.\n">>]),
+ Inc = [{includefile,YeccPre}],
+ {error,[{_,[{2,yecc,cannot_parse}]}],[]} =
+ yecc:file(Filename, Inc ++ Ret),
+
+ ok = file:write_file(Filename,
+ <<"%% coding: UTF-8
+ Nonterminals Hopp.
+ Terminals t.
+ Rootsymbol \"örn_Ѐ\".
+ Hopp -> t : '$1'.">>),
+ {error,[{Filename,[{4,yecc,{bad_symbol,"�rn_"++[1024]}}]}],[]} =
+ yecc:file(Filename, Ret),
+
+ ok = file:write_file(Filename,
+ <<"%% coding: UTF-8
+ Nonterminals Hopp.
+ Terminals t.
+ Rootsymbol Hopp.
+ Endsymbol \"örn_Ѐ\".
+ Hopp -> t : '$1'.">>),
+ {error,[{Filename,[{5,yecc,{bad_symbol,"�rn_"++[1024]}}]}],[]} =
+ yecc:file(Filename, Ret),
+
+ ok = file:write_file(Filename,
+ <<"%% coding: UTF-8
+ Nonterminals Hopp.
+ Terminals t.
+ Rootsymbol Hopp.
+ Expect \"örn_Ѐ\".
+ Hopp -> t : '$1'.">>),
+ {error,[{Filename,[{5,yecc,{bad_symbol,"�rn_"++[1024]}}]}],[]} =
+ yecc:file(Filename, Ret),
+
+ ok = file:write_file(Filename,
+ <<"%% coding: UTF-8
+ Nonterminals Hopp.
+ Terminals t.
+ Rootsymbol Hopp.
+ States \"örn_Ѐ\".
+ Hopp -> t : '$1'.">>),
+ {error,[{Filename,[{5,yecc,{bad_symbol,"�rn_"++[1024]}}]}],[]} =
+ yecc:file(Filename, Ret),
+
+ Ts = [{otp_10302_1,<<"
+ %% coding: UTF-8
+ Header \"%% örn_Ѐ\" \"%% \\x{400}B\".
+ Nonterminals Häpp list.
+ Terminals element.
+ Rootsymbol Häpp.
+
+ Häpp -> list : '$1'.
+
+ list -> element : '$1'.
+ list -> list element :
+ begin
+ Häpp = foo,
+ {Häpp, 'Häpp',\"\\x{400}B\",\"örn_Ѐ\"}
+ end.
+
+ Erlang code.
+
+ -export([t/0]).
+
+ t() ->
+ L = [{element, 1}, {element,2}],
+ {ok, R} = parse(L),
+ Häpp = foo,
+ {_,_,[1024,66],[246,114,110,95,1024]} = R,
+ {Häpp,'Häpp',\"\\x{400}B\",\"örn_Ѐ\"} = R,
+ ok.
+ ">>,default,ok},
+ {otp_10302_2,<<"
+ %% coding: Latin-1
+ Nonterminals H�pp list.
+ Terminals element.
+ Rootsymbol H�pp.
+
+ H�pp -> list : '$1'.
+
+ list -> element : '$1'.
+ list -> list element :
+ begin
+ H�pp = foo,
+ {H�pp, 'H�pp',\"\\x{400}B\",\"örn_Ѐ\"}
+ end.
+
+ Erlang code.
+
+ -export([t/0]).
+
+ t() ->
+ L = [{element, 1}, {element,2}],
+ {ok, R} = parse(L),
+ H�pp = foo,
+ {_,_,[1024,66],[195,182,114,110,95,208,128]} = R,
+ {H�pp,'H�pp',\"\\x{400}B\",\"örn_Ѐ\"} = R,
+ ok.
+ ">>,default,ok}],
+ run(Config, Ts),
+ ok.
+
yeccpre_size() ->
yeccpre_size(default_yeccpre()).
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 2ec1fcff9d..b240d53571 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2012</year>
+ <year>2013</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -60,8 +60,9 @@
<p><code>string = [bytes()]</code></p>
- <p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey'
- 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo'| 'PrivateKeyInfo' | 'CertificationRequest'</code></p>
+ <p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey' |
+ 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo' |
+ 'PrivateKeyInfo' | 'CertificationRequest'</code></p>
<p><code>pem_entry () = {pki_asn1_type(), binary(), %% DER or encrypted DER
not_encrypted | cipher_info()} </code></p>
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index fbe29753be..8437b7a623 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>2012</year>
+ <year>2013</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -274,7 +274,8 @@
</taglist>
<p>Example:</p>
- <p><code>erl -sasl releases_dir \"mytarget/releases\" -boot mytarget/releases/1.0/myrel -boot_var RELTOOL_EXT_LIB mytarget/lib</code></p>
+ <p><code>erl -sasl releases_dir \"mytarget/releases\" -boot mytarget/releases/1.0/myrel\
+ -boot_var RELTOOL_EXT_LIB mytarget/lib</code></p>
</item>
<tag><c>incl_sys_filters</c></tag>
diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl
index 6cb7ba0163..1f4ce7226a 100644
--- a/lib/reltool/src/reltool_target.erl
+++ b/lib/reltool/src/reltool_target.erl
@@ -482,33 +482,12 @@ do_gen_script(#rel{name = RelName, vsn = RelVsn},
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-load_app_mods(#app{mods = Mods} = App, Mand, PathFlag, Variables) ->
+load_app_mods(#app{mods = Mods0} = App, Mand, PathFlag, Variables) ->
Path = cr_path(App, PathFlag, Variables),
- PartNames =
- lists:sort([{packages:split(M),M} ||
- #mod{name = M, is_included=true} <- Mods,
- not lists:member(M, Mand)]),
- SplitMods =
- lists:foldl(
- fun({Parts,M}, [{Last, Acc}|Rest]) ->
- [_|Tail] = lists:reverse(Parts),
- case lists:reverse(Tail) of
- Subs when Subs == Last ->
- [{Last,[M|Acc]}|Rest];
- Subs ->
- [{Subs, [M]}|[{Last,Acc}|Rest]]
- end
- end,
- [{[],
- []}],
- PartNames),
- lists:foldl(
- fun({Subs,Ms}, Cmds) ->
- [{path, [filename:join([Path | Subs])]},
- {primLoad, lists:sort(Ms)} | Cmds]
- end,
- [],
- SplitMods).
+ Mods = [M || #mod{name = M, is_included=true} <- Mods0,
+ not lists:member(M, Mand)],
+ [{path, [filename:join([Path])]},
+ {primLoad, lists:sort(Mods)}].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% sort_used_and_incl_apps(Apps, OrderedApps) -> Apps
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
index c7c5cd4ff0..d8c82b2459 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>2011</year>
+ <year>1996</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -101,7 +101,8 @@
allowed:</p>
<pre>
4> <input>dbg:fun2ms(fun([M,N]) when N > X, is_atomm(M) -> return_trace() end).</input>
-Error: fun containing local erlang function calls ('is_atomm' called in guard) cannot be translated into match_spec
+Error: fun containing local erlang function calls ('is_atomm' called in guard)\
+ cannot be translated into match_spec
{error,transform_error}
5> <input>dbg:fun2ms(fun([M,N]) when N > X, is_atom(M) -> return_trace() end).</input>
[{['$1','$2'],[{'>','$2',{const,3}},{is_atom,'$1'}],[{return_trace}]}]</pre>
diff --git a/lib/runtime_tools/src/runtime_tools_sup.erl b/lib/runtime_tools/src/runtime_tools_sup.erl
index c8dab250dd..264e172a3c 100644
--- a/lib/runtime_tools/src/runtime_tools_sup.erl
+++ b/lib/runtime_tools/src/runtime_tools_sup.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -18,7 +19,7 @@
%%
%% ------------------------------------------------------------------------------
%% File : runtime_tools_sup.erl
-%% Author : Lennart �hman <[email protected]>
+%% Author : Lennart Öhman <[email protected]>
-module(runtime_tools_sup).
-behaviour(supervisor).
diff --git a/lib/sasl/src/overload.erl b/lib/sasl/src/overload.erl
index 5a4782efff..97f7bebe00 100644
--- a/lib/sasl/src/overload.erl
+++ b/lib/sasl/src/overload.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,7 +26,7 @@
format_status/2]).
%%%-----------------------------------------------------------------
-%%% This is a rewrite of overload from BS.3, by Peter H�gfeldt.
+%%% This is a rewrite of overload from BS.3, by Peter Högfeldt.
%%%
%%% DESCRIPTION
%%%
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 29c4a0d168..9b2e2c809b 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1067,11 +1067,10 @@ check_mod(Mod,App,Dir,Ext,IncPath) ->
end.
mod_to_filename(Dir, Mod, Ext) ->
- Parts = packages:split(Mod),
- filename:join([Dir | Parts]) ++ Ext.
+ filename:join(Dir, atom_to_list(Mod) ++ Ext).
check_module(Mod, Dir, ObjModTime, IncPath) ->
- {SrcDirs,_IncDirs}= smart_guess(Mod, Dir,IncPath),
+ {SrcDirs,_IncDirs}= smart_guess(Dir,IncPath),
case locate_src(Mod,SrcDirs) of
{ok,_FDir,_File,LastModTime} ->
if
@@ -1085,7 +1084,7 @@ check_module(Mod, Dir, ObjModTime, IncPath) ->
end.
locate_src(Mod,[Dir|Dirs]) ->
- File = filename:join(Dir, mod_to_fname(Mod) ++ ".erl"),
+ File = mod_to_filename(Dir, Mod, ".erl"),
case file:read_file_info(File) of
{ok,FileInfo} ->
LastModTime = FileInfo#file_info.mtime,
@@ -1096,9 +1095,6 @@ locate_src(Mod,[Dir|Dirs]) ->
locate_src(_,[]) ->
false.
-mod_to_fname(Mod) ->
- hd(lists:reverse(packages:split(Mod))).
-
%%______________________________________________________________________
%% smart_guess(Mod, Dir,IncludePath) -> {[Dirs],[IncDirs]}
@@ -1106,17 +1102,12 @@ mod_to_fname(Mod) ->
%% src-dir should be one of .../src or .../src/e_src
%% If dir does not contain .../ebin set dir to the same directory.
-smart_guess(Mod, Dir,IncPath) ->
+smart_guess(Dir,IncPath) ->
case reverse(filename:split(Dir)) of
["ebin"|D] ->
- Subdirs = case packages:split(Mod) of
- [_] -> [];
- [_|_] = Parts ->
- lists:reverse(tl(lists:reverse(Parts)))
- end,
D1 = reverse(D),
- Dirs = [filename:join(D1 ++ ["src" | Subdirs]),
- filename:join(D1 ++ ["src", "e_src" | Subdirs])],
+ Dirs = [filename:join(D1 ++ ["src"]),
+ filename:join(D1 ++ ["src", "e_src"])],
{Dirs,Dirs ++ IncPath};
_ ->
{[Dir],[Dir] ++ IncPath}
@@ -1423,23 +1414,8 @@ load_appl_mods([], _, _, _) ->
[{progress, modules_loaded}].
load_commands(Mods, Path) ->
- SplitMods = lists:foldl(
- fun({Parts,M}, [{Last, Acc}|Rest]) ->
- [_|Tail] = lists:reverse(Parts),
- case lists:reverse(Tail) of
- Subs when Subs == Last ->
- [{Last,[M|Acc]}|Rest];
- Subs ->
- [{Subs, [M]}|[{Last,Acc}|Rest]]
- end
- end, [{[],[]}],
- lists:sort([{packages:split(M),M} || M <- Mods])),
- lists:foldl(
- fun({Subs,Ms}, Cmds) ->
- [{path, [filename:join([Path | Subs])]},
- {primLoad,lists:sort(Ms)} | Cmds]
- end, [], SplitMods).
-
+ [{path, [filename:join([Path])]},
+ {primLoad,lists:sort(Mods)}].
%%______________________________________________________________________
%% Pack an application to an application term.
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 442837d57d..b6b8751f6c 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -126,6 +126,70 @@
<section>
+ <title>SNMP Development Toolkit 4.23</title>
+ <p>Version 4.23 supports code replacement in runtime from/to
+ version 4.22,
+ 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Documenting previously existing but undocumented function,
+ <seealso marker="snmp_generic#get_table_info">snmp_generic:get_table_info/2</seealso>. </p>
+ <p>Own Id: OTP-9942</p>
+ </item>
+
+ </list>
+-->
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Simultaneous
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ calls can interfere.
+ The master agent did not check if a backup was already in
+ progress when a backup request was accepted. </p>
+ <p>Own Id: OTP-9884</p>
+ <p>Aux Id: Seq 11995</p>
+ </item>
+
+ </list>
+ -->
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>[manager] The old Addr-and-Port based API functions, previously
+ long deprecated and marked for deletion in R16B, has now been
+ removed. </p>
+ <p>Own Id: OTP-10027</p>
+ </item>
+
+ </list>
+ </section>
+
+ </section> <!-- 4.23 -->
+
+
+ <section>
<title>SNMP Development Toolkit 4.22</title>
<p>Version 4.22 supports code replacement in runtime from/to
version 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index e6e188d5d5..07fdd208ff 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -279,7 +279,6 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv
<fsummary>Register this agent</fsummary>
<type>
<v>UserId = term()</v>
- <v>Addr = ip_address()</v>
<v>TargetName = target_name()</v>
<v>Config = [agent_config()]</v>
<v>agent_config() = {Item, Val}</v>
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 436f15eb9c..ad9540e886 100644
--- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
+++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
@@ -496,7 +496,7 @@ verify_vacmSecurityToGroupTable_col(_, Val) ->
%%
%%-----------------------------------------------------------------
vacmAccessTable(print) ->
- %% M�ste jag g�ra om alla entrien till {RowIdx, Row}?
+ %% Do I need to turn all entries into {RowIdx, Row}?
TableInfo = get_table(vacmAccessTable),
PrintRow =
fun(Prefix, Row) ->
diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl
index f590892c66..6ac0115dad 100644
--- a/lib/snmp/src/manager/snmpm.erl
+++ b/lib/snmp/src/manager/snmpm.erl
@@ -107,63 +107,9 @@
async_get_bulk/5, async_get_bulk/6, async_get_bulk/7, async_get_bulk/8
]).
-%% Backward compatibility exports (API version "1")
--deprecated({agent_info, 3}).
--deprecated({update_agent_info, 5}).
--deprecated({g, 3}).
--deprecated({g, 4}).
--deprecated({g, 5}).
--deprecated({g, 6}).
--deprecated({g, 7}).
--deprecated({ag, 3}).
--deprecated({ag, 4}).
--deprecated({ag, 5}).
--deprecated({ag, 6}).
--deprecated({ag, 7}).
--deprecated({gn, 3}).
--deprecated({gn, 4}).
--deprecated({gn, 5}).
--deprecated({gn, 6}).
--deprecated({gn, 7}).
--deprecated({agn, 3}).
--deprecated({agn, 4}).
--deprecated({agn, 5}).
--deprecated({agn, 6}).
--deprecated({agn, 7}).
--deprecated({gb, 5}).
--deprecated({gb, 6}).
--deprecated({gb, 7}).
--deprecated({gb, 8}).
--deprecated({gb, 9}).
--deprecated({agb, 5}).
--deprecated({agb, 6}).
--deprecated({agb, 7}).
--deprecated({agb, 8}).
--deprecated({agb, 9}).
--deprecated({s, 3}).
--deprecated({s, 4}).
--deprecated({s, 5}).
--deprecated({s, 6}).
--deprecated({s, 7}).
--deprecated({as, 3}).
--deprecated({as, 4}).
--deprecated({as, 5}).
--deprecated({as, 6}).
--deprecated({as, 7}).
--export([
- agent_info/3, update_agent_info/5,
- g/3, g/4, g/5, g/6, g/7,
- ag/3, ag/4, ag/5, ag/6, ag/7,
- gn/3, gn/4, gn/5, gn/6, gn/7,
- agn/3, agn/4, agn/5, agn/6, agn/7,
- gb/5, gb/6, gb/7, gb/8, gb/9,
- agb/5, agb/6, agb/7, agb/8, agb/9,
- s/3, s/4, s/5, s/6, s/7,
- as/3, as/4, as/5, as/6, as/7
- ]).
-
%% Application internal export
-export([start_link/3, snmpm_start_verify/2, snmpm_start_verify/3]).
+-export([target_name/1, target_name/2]).
-include_lib("snmp/src/misc/snmp_debug.hrl").
@@ -439,32 +385,16 @@ unregister_agent(UserId, Addr, Port) ->
Error
end.
+
agent_info(TargetName, Item) ->
snmpm_config:agent_info(TargetName, Item).
-%% Backward compatibility
-agent_info(Addr, Port, Item) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- agent_info(TargetName, Item);
- Error ->
- Error
- end.
-
update_agent_info(UserId, TargetName, Info) when is_list(Info) ->
snmpm_config:update_agent_info(UserId, TargetName, Info).
update_agent_info(UserId, TargetName, Item, Val) ->
update_agent_info(UserId, TargetName, [{Item, Val}]).
-%% Backward compatibility functions
-update_agent_info(UserId, Addr, Port, Item, Val) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- update_agent_info(UserId, TargetName, Item, Val);
- Error ->
- Error
- end.
which_agents() ->
snmpm_config:which_agents().
@@ -552,55 +482,6 @@ sync_get(UserId, TargetName, Context, Oids, Timeout, ExtraInfo) ->
%% </BACKWARD-COMPAT>
-%% <DEPRECATED>
-g(UserId, Addr, Oids) ->
- g(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids).
-
-g(UserId, Addr, CtxName, Oids) when is_list(CtxName) andalso is_list(Oids) ->
- g(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids);
-
-g(UserId, Addr, Port, Oids) when is_integer(Port) andalso is_list(Oids) ->
- g(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids);
-
-g(UserId, Addr, Oids, Timeout)
- when is_list(Oids) andalso is_integer(Timeout) ->
- g(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids, Timeout).
-
-g(UserId, Addr, Port, CtxName, Oids)
- when is_integer(Port) andalso is_list(CtxName) andalso is_list(Oids) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_get(UserId, TargetName, CtxName, Oids);
- Error ->
- Error
- end;
-
-g(UserId, Addr, Port, Oids, Timeout)
- when is_integer(Port) andalso is_list(Oids) andalso is_integer(Timeout) ->
- g(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids, Timeout);
-
-g(UserId, Addr, CtxName, Oids, Timeout)
- when is_list(CtxName) andalso is_list(Oids) andalso is_integer(Timeout) ->
- g(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids, Timeout).
-
-g(UserId, Addr, Port, CtxName, Oids, Timeout) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_get(UserId, TargetName, CtxName, Oids, Timeout);
- Error ->
- Error
- end.
-
-g(UserId, Addr, Port, CtxName, Oids, Timeout, ExtraInfo) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_get(UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo);
- Error ->
- Error
- end.
-%% </DEPRECATED>
-
-
%% --- asynchroneous get-request ---
%%
@@ -637,55 +518,6 @@ async_get(UserId, TargetName, Context, Oids, Expire, ExtraInfo) ->
%% </BACKWARD-COMPAT>
-%% <DEPRECATED>
-ag(UserId, Addr, Oids) ->
- ag(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids).
-
-ag(UserId, Addr, Port, Oids) when is_integer(Port) andalso is_list(Oids) ->
- ag(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids);
-
-ag(UserId, Addr, CtxName, Oids) when is_list(CtxName) andalso is_list(Oids) ->
- ag(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids);
-
-ag(UserId, Addr, Oids, Expire) when is_list(Oids) andalso is_integer(Expire) ->
- ag(UserId, Addr, ?DEFAULT_AGENT_PORT, ?DEFAULT_CONTEXT, Oids, Expire).
-
-ag(UserId, Addr, Port, CtxName, Oids)
- when is_integer(Port) andalso is_list(CtxName) andalso is_list(Oids) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get(UserId, TargetName, CtxName, Oids);
- Error ->
- Error
- end;
-
-ag(UserId, Addr, Port, Oids, Expire)
- when is_integer(Port) andalso is_list(Oids) andalso is_integer(Expire) ->
- ag(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids, Expire);
-
-ag(UserId, Addr, CtxName, Oids, Expire)
- when is_list(CtxName) andalso is_list(Oids) andalso is_integer(Expire) ->
- ag(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids, Expire).
-
-ag(UserId, Addr, Port, CtxName, Oids, Expire) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get(UserId, TargetName, CtxName, Oids, Expire);
- Error ->
- Error
- end.
-
-ag(UserId, Addr, Port, CtxName, Oids, Expire, ExtraInfo) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get(UserId, TargetName, CtxName, Oids, Expire, ExtraInfo);
- Error ->
- Error
- end.
-%% </DEPRECATED>
-
-
-
%% --- synchroneous get_next-request ---
%%
@@ -719,55 +551,6 @@ sync_get_next(UserId, TargetName, Context, Oids, Timeout, ExtraInfo) ->
%% </BACKWARD-COMPAT>
-%% <DEPRECATED>
-gn(UserId, Addr, Oids) ->
- gn(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids).
-
-gn(UserId, Addr, CtxName, Oids) when is_list(CtxName) andalso is_list(Oids) ->
- gn(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids);
-
-gn(UserId, Addr, Port, Oids) when is_integer(Port) andalso is_list(Oids) ->
- gn(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids);
-
-gn(UserId, Addr, Oids, Timeout)
- when is_list(Oids) andalso is_integer(Timeout) ->
- gn(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids, Timeout).
-
-gn(UserId, Addr, Port, CtxName, Oids)
- when is_integer(Port) andalso is_list(CtxName) andalso is_list(Oids) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_get_next(UserId, TargetName, CtxName, Oids);
- Error ->
- Error
- end;
-
-gn(UserId, Addr, Port, Oids, Timeout)
- when is_integer(Port) andalso is_list(Oids) andalso is_integer(Timeout) ->
- gn(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids, Timeout);
-gn(UserId, Addr, CtxName, Oids, Timeout)
- when is_list(CtxName) andalso is_list(Oids) andalso is_integer(Timeout) ->
- gn(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids, Timeout).
-
-gn(UserId, Addr, Port, CtxName, Oids, Timeout) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_get_next(UserId, TargetName, CtxName, Oids, Timeout);
- Error ->
- Error
- end.
-
-gn(UserId, Addr, Port, CtxName, Oids, Timeout, ExtraInfo) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_get_next(UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo);
- Error ->
- Error
- end.
-%% </DEPRECATED>
-
-
-
%% --- asynchroneous get_next-request ---
%%
@@ -801,56 +584,6 @@ async_get_next(UserId, TargetName, Context, Oids, Expire, ExtraInfo) ->
%% </BACKWARD-COMPAT>
-%% <DEPRECATED>
-agn(UserId, Addr, Oids) ->
- agn(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids).
-
-agn(UserId, Addr, CtxName, Oids) when is_list(CtxName) andalso is_list(Oids) ->
- agn(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids);
-
-agn(UserId, Addr, Port, Oids) when is_integer(Port) andalso is_list(Oids) ->
- agn(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids);
-
-agn(UserId, Addr, Oids, Expire)
- when is_list(Oids) andalso is_integer(Expire) ->
- agn(UserId, Addr, ?DEFAULT_AGENT_PORT, Oids, Expire).
-
-agn(UserId, Addr, Port, CtxName, Oids)
- when is_integer(Port) andalso is_list(CtxName) andalso is_list(Oids) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get_next(UserId, TargetName, CtxName, Oids);
- Error ->
- Error
- end;
-
-agn(UserId, Addr, Port, Oids, Expire)
- when is_integer(Port) andalso is_list(Oids) andalso is_integer(Expire) ->
- agn(UserId, Addr, Port, ?DEFAULT_CONTEXT, Oids, Expire);
-agn(UserId, Addr, CtxName, Oids, Expire)
- when is_list(CtxName) andalso is_list(CtxName) andalso is_integer(Expire) ->
- agn(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, Oids, Expire).
-
-agn(UserId, Addr, Port, CtxName, Oids, Expire) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get_next(UserId, TargetName, CtxName, Oids, Expire);
- Error ->
- Error
- end.
-
-agn(UserId, Addr, Port, CtxName, Oids, Expire, ExtraInfo) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get_next(UserId, TargetName, CtxName, Oids, Expire,
- ExtraInfo);
- Error ->
- Error
- end.
-%% </DEPRECATED>
-
-
-
%% --- synchroneous set-request ---
%%
@@ -884,64 +617,6 @@ sync_set(UserId, TargetName, Context, VarsAndVals, Timeout, ExtraInfo) ->
%% </BACKWARD-COMPAT>
-%% <DEPRECATED>
-s(UserId, Addr, VarsAndVals) ->
- s(UserId, Addr, ?DEFAULT_AGENT_PORT, VarsAndVals).
-
-s(UserId, Addr, Port, VarsAndVals)
- when is_integer(Port) andalso is_list(VarsAndVals) ->
- s(UserId, Addr, Port, ?DEFAULT_CONTEXT, VarsAndVals);
-
-s(UserId, Addr, CtxName, VarsAndVals)
- when is_list(CtxName) andalso is_list(VarsAndVals) ->
- s(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, VarsAndVals);
-
-s(UserId, Addr, VarsAndVals, Timeout)
- when is_list(VarsAndVals) andalso is_integer(Timeout) ->
- s(UserId, Addr, ?DEFAULT_AGENT_PORT, VarsAndVals, Timeout).
-
-s(UserId, Addr, Port, CtxName, VarsAndVals)
- when is_integer(Port) andalso
- is_list(CtxName) andalso
- is_list(VarsAndVals) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_set(UserId, TargetName, CtxName, VarsAndVals);
- Error ->
- Error
- end;
-
-s(UserId, Addr, Port, VarsAndVals, Timeout)
- when is_integer(Port) andalso
- is_list(VarsAndVals) andalso
- is_integer(Timeout) ->
- s(UserId, Addr, Port, ?DEFAULT_CONTEXT, VarsAndVals, Timeout);
-
-s(UserId, Addr, CtxName, VarsAndVals, Timeout)
- when is_list(CtxName) andalso
- is_list(VarsAndVals) andalso
- is_integer(Timeout) ->
- s(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, VarsAndVals, Timeout).
-
-s(UserId, Addr, Port, CtxName, VarsAndVals, Timeout) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_set(UserId, TargetName, CtxName, VarsAndVals, Timeout);
- Error ->
- Error
- end.
-
-s(UserId, Addr, Port, CtxName, VarsAndVals, Timeout, ExtraInfo) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_set(UserId, TargetName, CtxName, VarsAndVals, Timeout, ExtraInfo);
- Error ->
- Error
- end.
-%% </DEPRECATED>
-
-
-
%% --- asynchroneous set-request ---
%%
@@ -975,63 +650,6 @@ async_set(UserId, TargetName, Context, VarsAndVals, Expire, ExtraInfo) ->
%% </BACKWARD-COMPAT>
-%% <DEPRECATED>
-as(UserId, Addr, VarsAndVals) ->
- as(UserId, Addr, ?DEFAULT_AGENT_PORT, VarsAndVals).
-
-as(UserId, Addr, Port, VarsAndVals)
- when is_integer(Port) andalso is_list(VarsAndVals) ->
- as(UserId, Addr, Port, ?DEFAULT_CONTEXT, VarsAndVals);
-
-as(UserId, Addr, CtxName, VarsAndVals)
- when is_list(CtxName) andalso is_list(VarsAndVals) ->
- as(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, VarsAndVals);
-
-as(UserId, Addr, VarsAndVals, Expire)
- when is_list(VarsAndVals) andalso is_integer(Expire) ->
- as(UserId, Addr, ?DEFAULT_AGENT_PORT, VarsAndVals, Expire).
-
-as(UserId, Addr, Port, CtxName, VarsAndVals)
- when is_integer(Port) andalso
- is_list(CtxName) andalso
- is_list(VarsAndVals) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_set(UserId, TargetName, CtxName, VarsAndVals);
- Error ->
- Error
- end;
-
-as(UserId, Addr, Port, VarsAndVals, Expire)
- when is_integer(Port) andalso
- is_list(VarsAndVals) andalso
- is_integer(Expire) ->
- as(UserId, Addr, Port, ?DEFAULT_CONTEXT, VarsAndVals, Expire);
-
-as(UserId, Addr, CtxName, VarsAndVals, Expire)
- when is_list(CtxName) andalso
- is_list(VarsAndVals) andalso
- is_integer(Expire) ->
- as(UserId, Addr, ?DEFAULT_AGENT_PORT, CtxName, VarsAndVals, Expire).
-
-as(UserId, Addr, Port, CtxName, VarsAndVals, Expire) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_set(UserId, TargetName, CtxName, VarsAndVals, Expire);
- Error ->
- Error
- end.
-
-as(UserId, Addr, Port, CtxName, VarsAndVals, Expire, ExtraInfo) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_set(UserId, TargetName, CtxName, VarsAndVals, Expire, ExtraInfo);
- Error ->
- Error
- end.
-%% </DEPRECATED>
-
-
%% --- synchroneous get-bulk ---
%%
@@ -1091,162 +709,6 @@ sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Timeout,
%% </BACKWARD-COMPAT>
-%% <DEPRECATED>
-gb(UserId, Addr, NonRep, MaxRep, Oids) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n Oids: ~p",
- %% [UserId, Addr, NonRep, MaxRep, Oids]),
- gb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, Oids).
-
-gb(UserId, Addr, Port, NonRep, MaxRep, Oids)
- when is_integer(Port) andalso
- is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Oids) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n Port: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n Oids: ~p",
- %% [UserId, Addr, Port, NonRep, MaxRep, Oids]),
- gb(UserId, Addr, Port, NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids);
-
-gb(UserId, Addr, NonRep, MaxRep, CtxName, Oids)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(CtxName) andalso
- is_list(Oids) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n CtxName: ~p"
- %% "~n Oids: ~p",
- %% [UserId, Addr, NonRep, MaxRep, CtxName, Oids]),
- gb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, CtxName, Oids);
-
-gb(UserId, Addr, NonRep, MaxRep, Oids, Timeout)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Oids) andalso
- is_integer(Timeout) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n Oids: ~p"
- %% "~n Timeout: ~p",
- %% [UserId, Addr, NonRep, MaxRep, Oids, Timeout]),
- gb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, Oids, Timeout).
-
-gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids)
- when is_integer(Port) andalso
- is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(CtxName) andalso
- is_list(Oids) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n Port: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n CtxName: ~p"
- %% "~n Oids: ~p",
- %% [UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids]),
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- %% p("gb -> TargetName: ~p", [TargetName]),
- sync_get_bulk(UserId, TargetName, NonRep, MaxRep, CtxName, Oids);
- Error ->
- Error
- end;
-
-gb(UserId, Addr, Port, NonRep, MaxRep, Oids, Timeout)
- when is_integer(Port) andalso
- is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Oids) andalso
- is_integer(Timeout) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n Port: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n Oids: ~p"
- %% "~n Timeout: ~p",
- %% [UserId, Addr, Port, NonRep, MaxRep, Oids, Timeout]),
- gb(UserId, Addr, Port, NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids, Timeout);
-
-gb(UserId, Addr, NonRep, MaxRep, CtxName, Oids, Timeout)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(CtxName) andalso
- is_list(Oids) andalso
- is_integer(Timeout) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n CtxName: ~p"
- %% "~n Oids: ~p"
- %% "~n Timeout: ~p",
- %% [UserId, Addr, NonRep, MaxRep, CtxName, Oids, Timeout]),
- gb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, CtxName, Oids,
- Timeout).
-
-gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n Port: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n CtxName: ~p"
- %% "~n Oids: ~p"
- %% "~n Timeout: ~p",
- %% [UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout]),
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_get_bulk(UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids, Timeout);
- Error ->
- Error
- end.
-
-gb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo) ->
- %% p("gb -> entry with"
- %% "~n UserId: ~p"
- %% "~n Addr: ~p"
- %% "~n Port: ~p"
- %% "~n NonRep: ~p"
- %% "~n MaxRep: ~p"
- %% "~n CtxName: ~p"
- %% "~n Oids: ~p"
- %% "~n Timeout: ~p"
- %% "~n ExtraInfo: ~p",
- %% [UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo]),
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- sync_get_bulk(UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo);
- Error ->
- Error
- end.
-%% </DEPRECATED>
-
-
-
%% --- asynchroneous get-bulk ---
%%
@@ -1291,81 +753,6 @@ async_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Expire,
%% </BACKWARD-COMPAT>
-%% <DEPRECATED>
-agb(UserId, Addr, NonRep, MaxRep, Oids) ->
- agb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, Oids).
-
-agb(UserId, Addr, Port, NonRep, MaxRep, Oids)
- when is_integer(Port) andalso
- is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Oids) ->
- agb(UserId, Addr, Port, NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids);
-
-agb(UserId, Addr, NonRep, MaxRep, CtxName, Oids)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(CtxName) andalso
- is_list(Oids) ->
- agb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, CtxName, Oids);
-
-agb(UserId, Addr, NonRep, MaxRep, Oids, Expire)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Oids) andalso
- is_integer(Expire) ->
- agb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, Oids, Expire).
-
-agb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids)
- when is_integer(Port) andalso
- is_integer(NonRep) andalso
- is_integer(MaxRep),
- is_list(CtxName) andalso
- is_list(Oids) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get_bulk(UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids);
- Error ->
- Error
- end;
-
-agb(UserId, Addr, Port, NonRep, MaxRep, Oids, Expire)
- when is_integer(Port) andalso
- is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Oids) andalso
- is_integer(Expire) ->
- agb(UserId, Addr, Port, NonRep, MaxRep, ?DEFAULT_CONTEXT, Oids, Expire);
-
-agb(UserId, Addr, NonRep, MaxRep, CtxName, Oids, Expire)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(CtxName) andalso
- is_list(Oids) andalso
- is_integer(Expire) ->
- agb(UserId, Addr, ?DEFAULT_AGENT_PORT, NonRep, MaxRep, CtxName, Oids).
-
-agb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Expire) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get_bulk(UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids, Expire);
- Error ->
- Error
- end.
-
-agb(UserId, Addr, Port, NonRep, MaxRep, CtxName, Oids, Expire, ExtraInfo) ->
- case target_name(Addr, Port) of
- {ok, TargetName} ->
- async_get_bulk(UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids, Expire,
- ExtraInfo);
- Error ->
- Error
- end.
-%% </DEPRECATED>
-
cancel_async_request(UserId, ReqId) ->
snmpm_server:cancel_async_request(UserId, ReqId).
@@ -1457,7 +844,7 @@ sys_up_time() ->
format_reason(Reason) ->
format_reason("", Reason).
-format_reason(Prefix, Reason) when is_integer(Prefix) and (Prefix >= 0) ->
+format_reason(Prefix, Reason) when is_integer(Prefix) andalso (Prefix >= 0) ->
format_reason(lists:duplicate(Prefix, $ ), Reason);
format_reason(Prefix, Reason) when is_list(Prefix) ->
case (catch do_format_reason(Prefix, Reason)) of
@@ -1691,6 +1078,9 @@ format_vb_value(Prefix, _Type, Val) ->
%% --- Internal utility functions ---
%%
+target_name(Addr) ->
+ target_name(Addr, ?DEFAULT_AGENT_PORT).
+
target_name(Addr, Port) ->
snmpm_config:agent_info(Addr, Port, target_name).
diff --git a/lib/snmp/src/manager/snmpm_conf.erl b/lib/snmp/src/manager/snmpm_conf.erl
index e50508c489..03dbd028f7 100644
--- a/lib/snmp/src/manager/snmpm_conf.erl
+++ b/lib/snmp/src/manager/snmpm_conf.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -365,7 +366,7 @@ do_write_usm_conf(Fd,
do_write_usm_conf(Fd,
{EngineID, UserName, SecName,
AuthP, AuthKey, PrivP, PrivKey}) ->
- io:format(Fd, "{\"~s\", \"~s\", \"~s\", �~w, ~w, ~w, ~w}.~n",
+ io:format(Fd, "{\"~s\", \"~s\", \"~s\", í~w, ~w, ~w, ~w}.~n",
[EngineID, UserName, SecName, AuthP, AuthKey, PrivP, PrivKey]);
do_write_usm_conf(_Fd, Crap) ->
error({bad_usm_conf, Crap}).
diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl
index d7148bb4a4..953c94ab54 100644
--- a/lib/snmp/src/manager/snmpm_mpd.erl
+++ b/lib/snmp/src/manager/snmpm_mpd.erl
@@ -591,8 +591,8 @@ sec_engine_id(TargetName) ->
%% BMK BMK BMK
-%% Denna verkar v�ldigt lik generate_v1_v2c_response_msg!
-%% Gemensam? Borde det finnas olikheter?
+%% This one looks very similar to lik generate_v1_v2c_response_msg!
+%% Common/shared? Should there be differences?
%%
generate_v1_v2c_msg(Vsn, Pdu, Community, Log) ->
?vdebug("generate_v1_v2c_msg -> encode pdu", []),
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index bfe14bc080..09e1eb25a9 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -5752,14 +5753,14 @@ otp_4394_config(AgentConfDir, MgrDir, Ip0) ->
?line write_community_conf(AgentConfDir, [C1, C2]),
?line update_vacm(Vsn, AgentConfDir),
Ta1 = {"shelob v1",
- [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
+ [134,138,177,177], 5000, 1500, 3, %% Use Ip and modify
"pc1",
"target_v1", "",
%% [255,255,255,255,0,0],
[],
2048},
Ta2 = {"bifur v1",
- [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip
+ [134,138,177,75], 5000, 1500, 3, %% Use Ip
"pc2",
"target_v1", "",
%% [255,255,255,255,0,0],
diff --git a/lib/snmp/test/snmp_log_test.erl b/lib/snmp/test/snmp_log_test.erl
index aeac4d1f71..e9345b44cc 100644
--- a/lib/snmp/test/snmp_log_test.erl
+++ b/lib/snmp/test/snmp_log_test.erl
@@ -375,9 +375,9 @@ log_to_io1(Config) when is_list(Config) ->
%%======================================================================
-%% Starta en logger-process som med ett visst intervall loggar
-%% meddelanden. Starta en reader-process som vid ett viss tillf�lle
-%% l�ser fr�n loggen.
+%% Start a logger-process that logs messages with a certain interval.
+%% Start a reader-process that reads messages from the log at a certain
+%% point of time.
log_to_io2(suite) -> [];
log_to_io2(doc) -> "Log to io from a different process than which "
@@ -578,9 +578,9 @@ log_to_txt(Name, SeqNoGen, Config) when is_list(Config) ->
%%======================================================================
-%% Starta en logger-process som med ett visst intervall loggar
-%% meddelanden. Starta en reader-process som vid ett viss tillf�lle
-%% l�ser fr�n loggen.
+%% Start a logger-process that logs messages with a certain interval.
+%% Start a reader-process that reads messages from the log at a certain
+%% point of time.
%%
%% Test: ts:run(snmp, snmp_log_test, log_to_txt2, [batch]).
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index c374a2f0a6..dedbae5ce4 100644
--- a/lib/snmp/test/snmp_manager_test.erl
+++ b/lib/snmp/test/snmp_manager_test.erl
@@ -174,7 +174,26 @@ end_per_suite(Config) when is_list(Config) ->
init_per_testcase(Case, Config) when is_list(Config) ->
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE,Case]),
- init_per_testcase2(Case, Config).
+ %% This version of the API, based on Addr and Port, has been deprecated
+ DeprecatedApiCases =
+ [
+ simple_sync_get1,
+ simple_async_get1,
+ simple_sync_get_next1,
+ simple_async_get_next1,
+ simple_sync_set1,
+ simple_async_set1,
+ simple_sync_get_bulk1,
+ simple_async_get_bulk1,
+ misc_async1
+ ],
+ case lists:member(Case, DeprecatedApiCases) of
+ true ->
+ %% ?SKIP(api_no_longer_supported);
+ {skip, api_no_longer_supported};
+ false ->
+ init_per_testcase2(Case, Config)
+ end.
init_per_testcase2(Case, Config) ->
?DBG("init_per_testcase2 -> ~p", [erlang:nodes()]),
@@ -226,18 +245,6 @@ init_per_testcase2(Case, Config) ->
Conf2.
init_per_testcase3(Case, Config) ->
- ApiCases01 =
- [
- simple_sync_get1,
- simple_async_get1,
- simple_sync_get_next1,
- simple_async_get_next1,
- simple_sync_set1,
- simple_async_set1,
- simple_sync_get_bulk1,
- simple_async_get_bulk1,
- misc_async1
- ],
ApiCases02 =
[
simple_sync_get2,
@@ -273,7 +280,6 @@ init_per_testcase3(Case, Config) ->
inform_swarm,
report
] ++
- ApiCases01 ++
ApiCases02 ++
ApiCases03,
case lists:member(Case, Cases) of
@@ -319,18 +325,6 @@ end_per_testcase(Case, Config) when is_list(Config) ->
Conf2.
end_per_testcase2(Case, Config) ->
- ApiCases01 =
- [
- simple_sync_get1,
- simple_async_get1,
- simple_sync_get_next1,
- simple_async_get_next1,
- simple_sync_set1,
- simple_async_set1,
- simple_sync_get_bulk1,
- simple_async_get_bulk1,
- misc_async1
- ],
ApiCases02 =
[
simple_sync_get2,
@@ -366,7 +360,6 @@ end_per_testcase2(Case, Config) ->
inform_swarm,
report
] ++
- ApiCases01 ++
ApiCases02 ++
ApiCases03,
case lists:member(Case, Cases) of
@@ -1596,12 +1589,14 @@ register_agent3(Config) when is_list(Config) ->
simple_sync_get1(doc) -> ["Simple sync get-request - Old style (Addr & Port)"];
simple_sync_get1(suite) -> [];
simple_sync_get1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, ssg1),
p("starting with Config: ~p~n", [Config]),
Node = ?config(manager_node, Config),
- Addr = ?config(ip, Config),
+ Addr = ?config(manager_agent_target_name, Config),
Port = ?AGENT_PORT,
p("issue get-request without loading the mib"),
@@ -1757,6 +1752,8 @@ simple_async_get1(doc) ->
["Simple (async) get-request - Old style (Addr & Port)"];
simple_async_get1(suite) -> [];
simple_async_get1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, sag1),
p("starting with Config: ~p~n", [Config]),
@@ -1972,6 +1969,8 @@ simple_sync_get_next1(doc) -> ["Simple (sync) get_next-request - "
"Old style (Addr & Port)"];
simple_sync_get_next1(suite) -> [];
simple_sync_get_next1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, ssgn1),
p("starting with Config: ~p~n", [Config]),
@@ -2264,6 +2263,8 @@ simple_async_get_next1(doc) -> ["Simple (async) get_next-request - "
"Old style (Addr & Port)"];
simple_async_get_next1(suite) -> [];
simple_async_get_next1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, ssgn1),
p("starting with Config: ~p~n", [Config]),
@@ -2516,6 +2517,8 @@ simple_sync_set1(doc) -> ["Simple (sync) set-request - "
"Old style (Addr & Port)"];
simple_sync_set1(suite) -> [];
simple_sync_set1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, sss1),
p("starting with Config: ~p~n", [Config]),
@@ -2686,6 +2689,8 @@ simple_async_set1(doc) -> ["Simple (async) set-request - "
"Old style (Addr & Port)"];
simple_async_set1(suite) -> [];
simple_async_set1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, sas1),
p("starting with Config: ~p~n", [Config]),
@@ -2896,6 +2901,8 @@ simple_sync_get_bulk1(doc) -> ["Simple (sync) get_bulk-request - "
"Old style (Addr & Port)"];
simple_sync_get_bulk1(suite) -> [];
simple_sync_get_bulk1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, ssgb1),
p("starting with Config: ~p~n", [Config]),
@@ -3261,6 +3268,8 @@ simple_async_get_bulk1(doc) -> ["Simple (async) get_bulk-request - "
"Old style (Addr & Port)"];
simple_async_get_bulk1(suite) -> [];
simple_async_get_bulk1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, sagb1),
p("starting with Config: ~p~n", [Config]),
@@ -3605,6 +3614,8 @@ misc_async1(doc) -> ["Misc (async) request(s) - "
"Old style (Addr & Port)"];
misc_async1(suite) -> [];
misc_async1(Config) when is_list(Config) ->
+ ?SKIP(api_no_longer_supported),
+
process_flag(trap_exit, true),
put(tname, ms1),
p("starting with Config: ~p~n", [Config]),
@@ -5591,29 +5602,35 @@ fin_mgr_user(Conf) ->
init_mgr_user_data1(Conf) ->
Node = ?config(manager_node, Conf),
- Addr = ?config(ip, Conf),
- Port = ?AGENT_PORT,
- ?line ok = mgr_user_register_agent(Node, Addr, Port),
+ TargetName = ?config(manager_agent_target_name, Conf),
+ Addr = ?config(ip, Conf),
+ Port = ?AGENT_PORT,
+ ?line ok = mgr_user_register_agent(Node, TargetName,
+ [{address, Addr},
+ {port, Port},
+ {engine_id, "agentEngine"}]),
Agents = mgr_user_which_own_agents(Node),
?DBG("Own agents: ~p", [Agents]),
- ?line {ok, DefAgentConf} = mgr_user_agent_info(Node, Addr, Port, all),
+ ?line {ok, DefAgentConf} = mgr_user_agent_info(Node, TargetName, all),
?DBG("Default agent config: ~n~p", [DefAgentConf]),
- ?line ok = mgr_user_update_agent_info(Node, Addr, Port,
+ ?line ok = mgr_user_update_agent_info(Node, TargetName,
community, "all-rights"),
- ?line ok = mgr_user_update_agent_info(Node, Addr, Port,
+ ?line ok = mgr_user_update_agent_info(Node, TargetName,
sec_name, "all-rights"),
- ?line ok = mgr_user_update_agent_info(Node, Addr, Port,
+ ?line ok = mgr_user_update_agent_info(Node, TargetName,
engine_id, "agentEngine"),
- ?line ok = mgr_user_update_agent_info(Node, Addr, Port,
+ ?line ok = mgr_user_update_agent_info(Node, TargetName,
max_message_size, 1024),
- ?line {ok, AgentConf} = mgr_user_agent_info(Node, Addr, Port, all),
+ ?line {ok, AgentConf} = mgr_user_agent_info(Node, TargetName, all),
?DBG("Updated agent config: ~n~p", [AgentConf]),
Conf.
init_mgr_user_data2(Conf) ->
+ ?DBG("init_mgr_user_data2 -> entry with"
+ "~n Conf: ~p", [Conf]),
Node = ?config(manager_node, Conf),
TargetName = ?config(manager_agent_target_name, Conf),
Addr = ?config(ip, Conf),
@@ -5641,9 +5658,8 @@ init_mgr_user_data2(Conf) ->
fin_mgr_user_data1(Conf) ->
Node = ?config(manager_node, Conf),
- Addr = ?config(ip, Conf),
- Port = ?AGENT_PORT,
- mgr_user_unregister_agent(Node, Addr, Port),
+ TargetName = ?config(manager_agent_target_name, Conf),
+ mgr_user_unregister_agent(Node, TargetName),
mgr_user_which_own_agents(Node),
Conf.
@@ -5670,33 +5686,41 @@ mgr_user_stop(Node) ->
%% mgr_user_register_agent(Node, Addr, ?AGENT_PORT, []).
mgr_user_register_agent(Node, TargetName, Conf)
when is_list(TargetName) andalso is_list(Conf) ->
- rcall(Node, snmp_manager_user, register_agent, [TargetName, Conf]);
-mgr_user_register_agent(Node, Addr, Port) ->
- mgr_user_register_agent(Node, Addr, Port, []).
-mgr_user_register_agent(Node, Addr, Port, Conf) ->
- rcall(Node, snmp_manager_user, register_agent, [Addr, Port, Conf]).
+ rcall(Node, snmp_manager_user, register_agent, [TargetName, Conf]).
+%% <REMOVED-IN-R16B>
+%% mgr_user_register_agent(Node, Addr, Port) ->
+%% mgr_user_register_agent(Node, Addr, Port, []).
+%% mgr_user_register_agent(Node, Addr, Port, Conf) ->
+%% rcall(Node, snmp_manager_user, register_agent, [Addr, Port, Conf]).
+%% </REMOVED-IN-R16B>
%% mgr_user_unregister_agent(Node) ->
%% mgr_user_unregister_agent(Node, ?LOCALHOST(), ?AGENT_PORT).
-mgr_user_unregister_agent(Node, Addr_or_TargetName) ->
- rcall(Node, snmp_manager_user, unregister_agent, [Addr_or_TargetName]).
-mgr_user_unregister_agent(Node, Addr, Port) ->
- rcall(Node, snmp_manager_user, unregister_agent, [Addr, Port]).
-
-mgr_user_agent_info(Node, Addr_or_TargetName, Item) when is_atom(Item) ->
- rcall(Node, snmp_manager_user, agent_info, [Addr_or_TargetName, Item]).
-mgr_user_agent_info(Node, Addr, Port, Item) when is_atom(Item) ->
- rcall(Node, snmp_manager_user, agent_info, [Addr, Port, Item]).
+mgr_user_unregister_agent(Node, TargetName) when is_list(TargetName) ->
+ rcall(Node, snmp_manager_user, unregister_agent, [TargetName]).
+%% <REMOVED-IN-R16B>
+%% mgr_user_unregister_agent(Node, Addr, Port) ->
+%% rcall(Node, snmp_manager_user, unregister_agent, [Addr, Port]).
+%% </REMOVED-IN-R16B>
+
+mgr_user_agent_info(Node, TargetName, Item)
+ when is_list(TargetName) andalso is_atom(Item) ->
+ rcall(Node, snmp_manager_user, agent_info, [TargetName, Item]).
+%% <REMOVED-IN-R16B>
+%% mgr_user_agent_info(Node, Addr, Port, Item) when is_atom(Item) ->
+%% rcall(Node, snmp_manager_user, agent_info, [Addr, Port, Item]).
+%% </REMOVED-IN-R16B>
%% mgr_user_update_agent_info(Node, Item, Val) when atom(Item) ->
%% mgr_user_update_agent_info(Node, ?LOCALHOST(), ?AGENT_PORT, Item, Val).
-mgr_user_update_agent_info(Node, Addr_or_TargetName, Item, Val)
- when is_atom(Item) ->
- rcall(Node, snmp_manager_user, update_agent_info,
- [Addr_or_TargetName, Item, Val]).
-mgr_user_update_agent_info(Node, Addr, Port, Item, Val) when is_atom(Item) ->
- rcall(Node, snmp_manager_user, update_agent_info,
- [Addr, Port, Item, Val]).
+mgr_user_update_agent_info(Node, TargetName, Item, Val)
+ when is_list(TargetName) andalso is_atom(Item) ->
+ rcall(Node, snmp_manager_user, update_agent_info, [TargetName, Item, Val]).
+%% <REMOVED-IN-R16B>
+%% mgr_user_update_agent_info(Node, Addr, Port, Item, Val) when is_atom(Item) ->
+%% rcall(Node, snmp_manager_user, update_agent_info,
+%% [Addr, Port, Item, Val]).
+%% </REMOVED-IN-R16B>
%% mgr_user_which_all_agents(Node) ->
%% rcall(Node, snmp_manager_user, which_all_agents, []).
@@ -5709,89 +5733,112 @@ mgr_user_load_mib(Node, Mib) ->
%% mgr_user_sync_get(Node, Oids) ->
%% mgr_user_sync_get(Node, ?LOCALHOST(), ?AGENT_PORT, Oids).
-mgr_user_sync_get(Node, Addr_or_TargetName, Oids) ->
- rcall(Node, snmp_manager_user, sync_get, [Addr_or_TargetName, Oids]).
+mgr_user_sync_get(Node, TargetName, Oids) when is_list(TargetName) ->
+ rcall(Node, snmp_manager_user, sync_get, [TargetName, Oids]).
+%% <REMOVED-IN-R16B>
mgr_user_sync_get(Node, Addr, Port, Oids) ->
rcall(Node, snmp_manager_user, sync_get, [Addr, Port, Oids]).
+%% </REMOVED-IN-R16B>
-mgr_user_sync_get2(Node, TargetName, Oids, SendOpts) ->
+mgr_user_sync_get2(Node, TargetName, Oids, SendOpts) when is_list(TargetName) ->
rcall(Node, snmp_manager_user, sync_get2, [TargetName, Oids, SendOpts]).
%% mgr_user_async_get(Node, Oids) ->
%% mgr_user_async_get(Node, ?LOCALHOST(), ?AGENT_PORT, Oids).
-mgr_user_async_get(Node, Addr_or_TargetName, Oids) ->
- rcall(Node, snmp_manager_user, async_get, [Addr_or_TargetName, Oids]).
+mgr_user_async_get(Node, TargetName, Oids) when is_list(TargetName) ->
+ rcall(Node, snmp_manager_user, async_get, [TargetName, Oids]).
+%% <REMOVED-IN-R16B>
mgr_user_async_get(Node, Addr, Port, Oids) ->
rcall(Node, snmp_manager_user, async_get, [Addr, Port, Oids]).
+%% </REMOVED-IN-R16B>
-mgr_user_async_get2(Node, TargetName, Oids, SendOpts) ->
+mgr_user_async_get2(Node, TargetName, Oids, SendOpts)
+ when is_list(TargetName) ->
rcall(Node, snmp_manager_user, async_get2, [TargetName, Oids, SendOpts]).
%% mgr_user_sync_get_next(Node, Oids) ->
%% mgr_user_sync_get_next(Node, ?LOCALHOST(), ?AGENT_PORT, Oids).
-mgr_user_sync_get_next(Node, Addr_or_TargetName, Oids) ->
- rcall(Node, snmp_manager_user, sync_get_next, [Addr_or_TargetName, Oids]).
+mgr_user_sync_get_next(Node, TargetName, Oids) when is_list(TargetName) ->
+ rcall(Node, snmp_manager_user, sync_get_next, [TargetName, Oids]).
+%% <REMOVED-IN-R16B>
mgr_user_sync_get_next(Node, Addr, Port, Oids) ->
rcall(Node, snmp_manager_user, sync_get_next, [Addr, Port, Oids]).
+%% </REMOVED-IN-R16B>
-mgr_user_sync_get_next2(Node, TargetName, Oids, SendOpts) ->
+mgr_user_sync_get_next2(Node, TargetName, Oids, SendOpts)
+ when is_list(TargetName) ->
rcall(Node, snmp_manager_user, sync_get_next2, [TargetName, Oids, SendOpts]).
%% mgr_user_async_get_next(Node, Oids) ->
%% mgr_user_async_get_next(Node, ?LOCALHOST(), ?AGENT_PORT, Oids).
-mgr_user_async_get_next(Node, Addr_or_TargetName, Oids) ->
- rcall(Node, snmp_manager_user, async_get_next, [Addr_or_TargetName, Oids]).
+mgr_user_async_get_next(Node, TargetName, Oids) when is_list(TargetName) ->
+ rcall(Node, snmp_manager_user, async_get_next, [TargetName, Oids]).
+%% <REMOVED-IN-R16B>
mgr_user_async_get_next(Node, Addr, Port, Oids) ->
rcall(Node, snmp_manager_user, async_get_next, [Addr, Port, Oids]).
+%% </REMOVED-IN-R16B>
-mgr_user_async_get_next2(Node, TargetName, Oids, SendOpts) ->
+mgr_user_async_get_next2(Node, TargetName, Oids, SendOpts)
+ when is_list(TargetName) ->
rcall(Node, snmp_manager_user, async_get_next2, [TargetName, Oids, SendOpts]).
%% mgr_user_sync_set(Node, VAV) ->
%% mgr_user_sync_set(Node, ?LOCALHOST(), ?AGENT_PORT, VAV).
-mgr_user_sync_set(Node, Addr_or_TargetName, VAV) ->
- rcall(Node, snmp_manager_user, sync_set, [Addr_or_TargetName, VAV]).
+mgr_user_sync_set(Node, TargetName, VAV) when is_list(TargetName) ->
+ rcall(Node, snmp_manager_user, sync_set, [TargetName, VAV]).
+%% <REMOVED-IN-R16B>
mgr_user_sync_set(Node, Addr, Port, VAV) ->
rcall(Node, snmp_manager_user, sync_set, [Addr, Port, VAV]).
+%% </REMOVED-IN-R16B>
-mgr_user_sync_set2(Node, TargetName, VAV, SendOpts) ->
+mgr_user_sync_set2(Node, TargetName, VAV, SendOpts) when is_list(TargetName) ->
rcall(Node, snmp_manager_user, sync_set2, [TargetName, VAV, SendOpts]).
%% mgr_user_async_set(Node, VAV) ->
%% mgr_user_async_set(Node, ?LOCALHOST(), ?AGENT_PORT, VAV).
-mgr_user_async_set(Node, Addr_or_TargetName, VAV) ->
- rcall(Node, snmp_manager_user, async_set, [Addr_or_TargetName, VAV]).
+mgr_user_async_set(Node, TargetName, VAV) when is_list(TargetName) ->
+ rcall(Node, snmp_manager_user, async_set, [TargetName, VAV]).
+%% <REMOVED-IN-R16B>
mgr_user_async_set(Node, Addr, Port, VAV) ->
rcall(Node, snmp_manager_user, async_set, [Addr, Port, VAV]).
+%% </REMOVED-IN-R16B>
-mgr_user_async_set2(Node, TargetName, VAV, SendOpts) ->
+mgr_user_async_set2(Node, TargetName, VAV, SendOpts) when is_list(TargetName) ->
rcall(Node, snmp_manager_user, async_set2, [TargetName, VAV, SendOpts]).
%% mgr_user_sync_get_bulk(Node, NonRep, MaxRep, Oids) ->
%% mgr_user_sync_get_bulk(Node, ?LOCALHOST(), ?AGENT_PORT,
%% NonRep, MaxRep, Oids).
-mgr_user_sync_get_bulk(Node, Addr_or_TargetName, NonRep, MaxRep, Oids) ->
+mgr_user_sync_get_bulk(Node, TargetName, NonRep, MaxRep, Oids)
+ when is_list(TargetName) ->
rcall(Node, snmp_manager_user, sync_get_bulk,
- [Addr_or_TargetName, NonRep, MaxRep, Oids]).
+ [TargetName, NonRep, MaxRep, Oids]).
+%% <REMOVED-IN-R16B>
mgr_user_sync_get_bulk(Node, Addr, Port, NonRep, MaxRep, Oids) ->
rcall(Node, snmp_manager_user, sync_get_bulk,
[Addr, Port, NonRep, MaxRep, Oids]).
+%% </REMOVED-IN-R16B>
-mgr_user_sync_get_bulk2(Node, TargetName, NonRep, MaxRep, Oids, SendOpts) ->
+mgr_user_sync_get_bulk2(Node, TargetName, NonRep, MaxRep, Oids, SendOpts)
+ when is_list(TargetName) ->
rcall(Node, snmp_manager_user, sync_get_bulk2,
[TargetName, NonRep, MaxRep, Oids, SendOpts]).
%% mgr_user_async_get_bulk(Node, NonRep, MaxRep, Oids) ->
%% mgr_user_async_get_bulk(Node, ?LOCALHOST(), ?AGENT_PORT,
%% NonRep, MaxRep, Oids).
-mgr_user_async_get_bulk(Node, Addr_or_TargetName, NonRep, MaxRep, Oids) ->
+mgr_user_async_get_bulk(Node, TargetName, NonRep, MaxRep, Oids)
+ when is_list(TargetName) ->
rcall(Node, snmp_manager_user, async_get_bulk,
- [Addr_or_TargetName, NonRep, MaxRep, Oids]).
+ [TargetName, NonRep, MaxRep, Oids]).
+%% <REMOVED-IN-R16B>
mgr_user_async_get_bulk(Node, Addr, Port, NonRep, MaxRep, Oids) ->
rcall(Node, snmp_manager_user, async_get_bulk,
[Addr, Port, NonRep, MaxRep, Oids]).
+%% </REMOVED-IN-R16B>
-mgr_user_async_get_bulk2(Node, TargetName, NonRep, MaxRep, Oids, SendOpts) ->
+mgr_user_async_get_bulk2(Node, TargetName, NonRep, MaxRep, Oids, SendOpts)
+ when is_list(TargetName) ->
rcall(Node, snmp_manager_user, async_get_bulk2,
[TargetName, NonRep, MaxRep, Oids, SendOpts]).
diff --git a/lib/snmp/test/snmp_manager_user.erl b/lib/snmp/test/snmp_manager_user.erl
index 1b62b04960..4e789bbaec 100644
--- a/lib/snmp/test/snmp_manager_user.erl
+++ b/lib/snmp/test/snmp_manager_user.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -44,20 +44,20 @@
info/0,
system_info/0,
simulate_crash/1,
- register_agent/2, register_agent/3,
- unregister_agent/1, unregister_agent/2,
- agent_info/2, agent_info/3,
- update_agent_info/3, update_agent_info/4,
+ register_agent/2,
+ unregister_agent/1,
+ agent_info/2,
+ update_agent_info/3,
which_all_agents/0, which_own_agents/0,
load_mib/1, unload_mib/1,
- sync_get/1, sync_get/2, sync_get/3, sync_get2/3,
- async_get/1, async_get/2, async_get/3, async_get2/3,
- sync_get_next/1, sync_get_next/2, sync_get_next/3, sync_get_next2/3,
- async_get_next/1, async_get_next/2, async_get_next/3, async_get_next2/3,
- sync_set/1, sync_set/2, sync_set/3, sync_set2/3,
- async_set/1, async_set/2, async_set/3, async_set2/3,
- sync_get_bulk/3, sync_get_bulk/4, sync_get_bulk/5, sync_get_bulk2/5,
- async_get_bulk/3, async_get_bulk/4, async_get_bulk/5, async_get_bulk2/5,
+ sync_get/1, sync_get/2, sync_get2/3,
+ async_get/1, async_get/2, async_get2/3,
+ sync_get_next/1, sync_get_next/2, sync_get_next2/3,
+ async_get_next/1, async_get_next/2, async_get_next2/3,
+ sync_set/1, sync_set/2, sync_set2/3,
+ async_set/1, async_set/2, async_set2/3,
+ sync_get_bulk/3, sync_get_bulk/4, sync_get_bulk2/5,
+ async_get_bulk/3, async_get_bulk/4, async_get_bulk2/5,
name_to_oid/1, oid_to_name/1,
purify_oid/1
]).
@@ -73,15 +73,11 @@
-export([
handle_error/3,
- handle_agent/4,
+ handle_agent/5,
handle_pdu/4,
handle_trap/3,
handle_inform/3,
- handle_report/3,
- handle_pdu/5, % For backwards compatibillity
- handle_trap/4, % For backwards compatibillity
- handle_inform/4, % For backwards compatibillity
- handle_report/4 % For backwards compatibillity
+ handle_report/3
]).
@@ -126,27 +122,16 @@ simulate_crash(Reason) ->
register_agent(TargetName, Config)
when is_list(TargetName) andalso is_list(Config) ->
- call({register_agent, TargetName, Config});
-register_agent(Addr, Port) ->
- register_agent(Addr, Port, []).
-
-register_agent(Addr, Port, Conf) ->
- call({register_agent, Addr, Port, Conf}).
+ call({register_agent, TargetName, Config}).
unregister_agent(TargetName) ->
call({unregister_agent, TargetName}).
-unregister_agent(Addr, Port) ->
- call({unregister_agent, Addr, Port}).
agent_info(TargetName, Item) ->
call({agent_info, TargetName, Item}).
-agent_info(Addr, Port, Item) ->
- call({agent_info, Addr, Port, Item}).
update_agent_info(TargetName, Item, Val) ->
call({update_agent_info, TargetName, Item, Val}).
-update_agent_info(Addr, Port, Item, Val) ->
- call({update_agent_info, Addr, Port, Item, Val}).
which_all_agents() ->
call(which_all_agents).
@@ -165,11 +150,8 @@ unload_mib(Mib) ->
sync_get(Oids) ->
call({sync_get, Oids}).
-sync_get(Addr_or_TargetName, Oids) ->
- call({sync_get, Addr_or_TargetName, Oids}).
-
-sync_get(Addr, Port, Oids) ->
- call({sync_get, Addr, Port, Oids}).
+sync_get(TargetName, Oids) ->
+ call({sync_get, TargetName, Oids}).
sync_get2(TargetName, Oids, SendOpts) ->
call({sync_get2, TargetName, Oids, SendOpts}).
@@ -180,11 +162,8 @@ sync_get2(TargetName, Oids, SendOpts) ->
async_get(Oids) ->
call({async_get, Oids}).
-async_get(Addr_or_TargetName, Oids) ->
- call({async_get, Addr_or_TargetName, Oids}).
-
-async_get(Addr, Port, Oids) ->
- call({async_get, Addr, Port, Oids}).
+async_get(TargetName, Oids) ->
+ call({async_get, TargetName, Oids}).
async_get2(TargetName, Oids, SendOpts) ->
call({async_get2, TargetName, Oids, SendOpts}).
@@ -194,11 +173,8 @@ async_get2(TargetName, Oids, SendOpts) ->
sync_get_next(Oids) ->
call({sync_get_next, Oids}).
-sync_get_next(Addr_or_TargetName, Oids) ->
- call({sync_get_next, Addr_or_TargetName, Oids}).
-
-sync_get_next(Addr, Port, Oids) ->
- call({sync_get_next, Addr, Port, Oids}).
+sync_get_next(TargetName, Oids) ->
+ call({sync_get_next, TargetName, Oids}).
sync_get_next2(TargetName, Oids, SendOpts) ->
call({sync_get_next2, TargetName, Oids, SendOpts}).
@@ -208,11 +184,8 @@ sync_get_next2(TargetName, Oids, SendOpts) ->
async_get_next(Oids) ->
call({async_get_next, Oids}).
-async_get_next(Addr_or_TargetName, Oids) ->
- call({async_get_next, Addr_or_TargetName, Oids}).
-
-async_get_next(Addr, Port, Oids) ->
- call({async_get_next, Addr, Port, Oids}).
+async_get_next(TargetName, Oids) ->
+ call({async_get_next, TargetName, Oids}).
async_get_next2(TargetName, Oids, SendOpts) ->
call({async_get_next2, TargetName, Oids, SendOpts}).
@@ -222,11 +195,8 @@ async_get_next2(TargetName, Oids, SendOpts) ->
sync_set(VAV) ->
call({sync_set, VAV}).
-sync_set(Addr_or_TargetName, VAV) ->
- call({sync_set, Addr_or_TargetName, VAV}).
-
-sync_set(Addr, Port, VAV) ->
- call({sync_set, Addr, Port, VAV}).
+sync_set(TargetName, VAV) ->
+ call({sync_set, TargetName, VAV}).
sync_set2(TargetName, VAV, SendOpts) ->
call({sync_set2, TargetName, VAV, SendOpts}).
@@ -236,11 +206,8 @@ sync_set2(TargetName, VAV, SendOpts) ->
async_set(VAV) ->
call({async_set, VAV}).
-async_set(Addr_or_TargetName, VAV) ->
- call({async_set, Addr_or_TargetName, VAV}).
-
-async_set(Addr, Port, VAV) ->
- call({async_set, Addr, Port, VAV}).
+async_set(TargetName, VAV) ->
+ call({async_set, TargetName, VAV}).
async_set2(TargetName, VAV, SendOpts) ->
call({async_set2, TargetName, VAV, SendOpts}).
@@ -250,11 +217,8 @@ async_set2(TargetName, VAV, SendOpts) ->
sync_get_bulk(NonRep, MaxRep, Oids) ->
call({sync_get_bulk, NonRep, MaxRep, Oids}).
-sync_get_bulk(Addr_or_TargetName, NonRep, MaxRep, Oids) ->
- call({sync_get_bulk, Addr_or_TargetName, NonRep, MaxRep, Oids}).
-
-sync_get_bulk(Addr, Port, NonRep, MaxRep, Oids) ->
- call({sync_get_bulk, Addr, Port, NonRep, MaxRep, Oids}).
+sync_get_bulk(TargetName, NonRep, MaxRep, Oids) ->
+ call({sync_get_bulk, TargetName, NonRep, MaxRep, Oids}).
sync_get_bulk2(TargetName, NonRep, MaxRep, Oids, SendOpts) ->
call({sync_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts}).
@@ -264,11 +228,8 @@ sync_get_bulk2(TargetName, NonRep, MaxRep, Oids, SendOpts) ->
async_get_bulk(NonRep, MaxRep, Oids) ->
call({async_get_bulk, NonRep, MaxRep, Oids}).
-async_get_bulk(Addr_or_TargetName, NonRep, MaxRep, Oids) ->
- call({async_get_bulk, Addr_or_TargetName, NonRep, MaxRep, Oids}).
-
-async_get_bulk(Addr, Port, NonRep, MaxRep, Oids) ->
- call({async_get_bulk, Addr, Port, NonRep, MaxRep, Oids}).
+async_get_bulk(TargetName, NonRep, MaxRep, Oids) ->
+ call({async_get_bulk, TargetName, NonRep, MaxRep, Oids}).
async_get_bulk2(TargetName, NonRep, MaxRep, Oids, SendOpts) ->
call({async_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts}).
@@ -340,24 +301,12 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{register_agent, Addr, Port, Conf}, From, Ref} ->
- d("loop -> received register_agent request"),
- Res = snmpm:register_agent(Id, Addr, Port, Conf),
- reply(From, Res, Ref),
- loop(S);
-
{{unregister_agent, TargetName}, From, Ref} ->
d("loop -> received unregister_agent request"),
Res = snmpm:unregister_agent(Id, TargetName),
reply(From, Res, Ref),
loop(S);
- {{unregister_agent, Addr, Port}, From, Ref} ->
- d("loop -> received unregister_agent request"),
- Res = snmpm:unregister_agent(Id, Addr, Port),
- reply(From, Res, Ref),
- loop(S);
-
{{agent_info, TargetName, Item}, From, Ref} ->
d("loop -> received agent_info request with"
"~n TargetName: ~p"
@@ -368,15 +317,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{agent_info, Addr, Port, Item}, From, Ref} ->
- d("loop -> received agent_info request with"
- "~n Addr: ~p"
- "~n Port: ~p"
- "~n Item: ~p", [Addr, Port, Item]),
- Res = snmpm:agent_info(Addr, Port, Item),
- reply(From, Res, Ref),
- loop(S);
-
{{update_agent_info, TargetName, Item, Val}, From, Ref} ->
d("loop -> received update_agent_info request with"
"~n TargetName: ~p"
@@ -386,16 +326,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{update_agent_info, Addr, Port, Item, Val}, From, Ref} ->
- d("loop -> received update_agent_info request with"
- "~n Addr: ~p"
- "~n Port: ~p"
- "~n Item: ~p"
- "~n Val: ~p", [Addr, Port, Item, Val]),
- Res = snmpm:update_agent_info(Id, Addr, Port, Item, Val),
- reply(From, Res, Ref),
- loop(S);
-
{which_all_agents, From, Ref} ->
d("loop -> received which_all_agents request"),
Res = snmpm:which_agents(),
@@ -452,23 +382,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{sync_get, Addr, Oids}, From, Ref} ->
- d("loop -> received sync_get request with"
- "~n Addr: ~p"
- "~n Oids: ~p", [Addr, Oids]),
- Res = snmpm:g(Id, Addr, Oids),
- reply(From, Res, Ref),
- loop(S);
-
- {{sync_get, Addr, Port, Oids}, From, Ref} ->
- d("loop -> received sync_get request with"
- "~n Addr: ~p"
- "~n Port: ~p"
- "~n Oids: ~p", [Addr, Port, Oids]),
- Res = snmpm:g(Id, Addr, Port, Oids),
- reply(From, Res, Ref),
- loop(S);
-
%%
%% -- (async) get-request --
@@ -500,18 +413,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{async_get, Addr, Oids}, From, Ref} ->
- d("loop -> received async_get request"),
- Res = snmpm:ag(Id, Addr, Oids),
- reply(From, Res, Ref),
- loop(S);
-
- {{async_get, Addr, Port, Oids}, From, Ref} ->
- d("loop -> received async_get request"),
- Res = snmpm:ag(Id, Addr, Port, Oids),
- reply(From, Res, Ref),
- loop(S);
-
%%
%% -- (sync) get_next-request --
@@ -543,18 +444,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{sync_get_next, Addr, Oids}, From, Ref} ->
- d("loop -> received sync_get_next request"),
- Res = snmpm:gn(Id, Addr, Oids),
- reply(From, Res, Ref),
- loop(S);
-
- {{sync_get_next, Addr, Port, Oids}, From, Ref} ->
- d("loop -> received sync_get_next request"),
- Res = snmpm:gn(Id, Addr, Port, Oids),
- reply(From, Res, Ref),
- loop(S);
-
%%
%% -- (async) get_next-request --
@@ -586,18 +475,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{async_get_next, Addr, Oids}, From, Ref} ->
- d("loop -> received async_get_next request"),
- Res = snmpm:agn(Id, Addr, Oids),
- reply(From, Res, Ref),
- loop(S);
-
- {{async_get_next, Addr, Port, Oids}, From, Ref} ->
- d("loop -> received async_get_next request"),
- Res = snmpm:agn(Id, Addr, Port, Oids),
- reply(From, Res, Ref),
- loop(S);
-
%%
%% -- (sync) set-request --
@@ -626,18 +503,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{sync_set, Addr, VAV}, From, Ref} ->
- d("loop -> received sync_set request"),
- Res = snmpm:s(Id, Addr, VAV),
- reply(From, Res, Ref),
- loop(S);
-
- {{sync_set, Addr, Port, VAV}, From, Ref} ->
- d("loop -> received sync_set request"),
- Res = snmpm:s(Id, Addr, Port, VAV),
- reply(From, Res, Ref),
- loop(S);
-
%%
%% -- (async) set-request --
@@ -666,18 +531,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{async_set, Addr, VAV}, From, Ref} ->
- d("loop -> received async_set request"),
- Res = snmpm:as(Id, Addr, VAV),
- reply(From, Res, Ref),
- loop(S);
-
- {{async_set, Addr, Port, VAV}, From, Ref} ->
- d("loop -> received async_set request"),
- Res = snmpm:as(Id, Addr, Port, VAV),
- reply(From, Res, Ref),
- loop(S);
-
%%
%% -- (sync) get-bulk-request --
@@ -718,27 +571,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{sync_get_bulk, Addr, NonRep, MaxRep, Oids}, From, Ref} ->
- d("loop -> received sync_get_bulk request with"
- "~n Addr: ~p"
- "~n NonRep: ~w"
- "~n MaxRep: ~w"
- "~n Oids: ~p", [Addr, NonRep, MaxRep, Oids]),
- Res = snmpm:gb(Id, Addr, NonRep, MaxRep, Oids),
- reply(From, Res, Ref),
- loop(S);
-
- {{sync_get_bulk, Addr, Port, NonRep, MaxRep, Oids}, From, Ref} ->
- d("loop -> received sync_get_bulk request with"
- "~n Addr: ~p"
- "~n Port: ~w"
- "~n NonRep: ~w"
- "~n MaxRep: ~w"
- "~n Oids: ~p", [Addr, Port, NonRep, MaxRep, Oids]),
- Res = snmpm:gb(Id, Addr, Port, NonRep, MaxRep, Oids),
- reply(From, Res, Ref),
- loop(S);
-
%%
%% -- (async) get-bulk-request --
@@ -779,27 +611,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
reply(From, Res, Ref),
loop(S);
- {{async_get_bulk, Addr, NonRep, MaxRep, Oids}, From, Ref} ->
- d("loop -> received async_get_bulk request with"
- "~n Addr: ~p"
- "~n NonRep: ~w"
- "~n MaxRep: ~w"
- "~n Oids: ~p", [Addr, NonRep, MaxRep, Oids]),
- Res = snmpm:agb(Id, Addr, NonRep, MaxRep, Oids),
- reply(From, Res, Ref),
- loop(S);
-
- {{async_get_bulk, Addr, Port, NonRep, MaxRep, Oids}, From, Ref} ->
- d("loop -> received async_get_bulk request with"
- "~n Addr: ~p"
- "~n Port: ~w"
- "~n NonRep: ~w"
- "~n MaxRep: ~w"
- "~n Oids: ~p", [Addr, Port, NonRep, MaxRep, Oids]),
- Res = snmpm:agb(Id, Addr, Port, NonRep, MaxRep, Oids),
- reply(From, Res, Ref),
- loop(S);
-
%%
%% -- logical name translation --
@@ -846,12 +657,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
Parent ! {async_event, ReqId, {pdu, SnmpResponse}},
loop(S);
- %% For backwards compatibillity
- {handle_pdu, _Pid, _Addr, _Port, ReqId, SnmpResponse} ->
- d("loop -> received pdu callback from manager for ~w", [ReqId]),
- Parent ! {async_event, ReqId, {pdu, SnmpResponse}},
- loop(S);
-
{handle_trap, _Pid, TargetName, SnmpTrap} ->
d("loop -> received trap callback from manager for "
"~n ~p",
@@ -860,15 +665,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
Parent ! {async_event, TargetName, {trap, SnmpTrap}},
loop(S);
- %% For backwards compatibillity
- {handle_trap, _Pid, Addr, Port, SnmpTrap} ->
- d("loop -> received trap callback from manager for "
- "~n ~p:~w",
- "~n ~p",
- [Addr, Port, SnmpTrap]),
- Parent ! {async_event, {Addr, Port}, {trap, SnmpTrap}},
- loop(S);
-
{handle_inform, Pid, TargetName, SnmpInform} ->
d("loop -> received inform callback from manager for "
"~n ~p",
@@ -877,15 +673,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
Parent ! {async_event, TargetName, {inform, Pid, SnmpInform}},
loop(S);
- %% For backwards compatibillity
- {handle_inform, Pid, Addr, Port, SnmpInform} ->
- d("loop -> received inform callback from manager for "
- "~n ~p:~w",
- "~n ~p",
- [Addr, Port, SnmpInform]),
- Parent ! {async_event, {Addr, Port}, {inform, Pid, SnmpInform}},
- loop(S);
-
{handle_report, _Pid, TargetName, SnmpReport} ->
d("loop -> received report callback from manager for "
"~n ~p",
@@ -894,15 +681,6 @@ loop(#state{parent = Parent, id = Id} = S) ->
Parent ! {async_event, TargetName, {report, SnmpReport}},
loop(S);
- %% For backwards compatibillity
- {handle_report, _Pid, Addr, Port, SnmpReport} ->
- d("loop -> received report callback from manager for "
- "~n ~p:~w",
- "~n ~p",
- [Addr, Port, SnmpReport]),
- Parent ! {async_event, {Addr, Port}, {report, SnmpReport}},
- loop(S);
-
{'EXIT', Parent, Reason} ->
d("received exit signal from parent: ~n~p", [Reason]),
info("received exit signal from parent: ~n~p", [Reason]),
@@ -981,8 +759,8 @@ handle_error(ReqId, Reason, UserPid) ->
ignore.
-handle_agent(Addr, Port, SnmpInfo, UserPid) ->
- UserPid ! {handle_agent, self(), Addr, Port, SnmpInfo},
+handle_agent(Addr, Port, SnmpInfo, UserPid, UserData) ->
+ UserPid ! {handle_agent, self(), Addr, Port, SnmpInfo, UserData},
ignore.
@@ -990,22 +768,10 @@ handle_pdu(TargetName, ReqId, SnmpResponse, UserPid) ->
UserPid ! {handle_pdu, self(), TargetName, ReqId, SnmpResponse},
ignore.
-%% For backwards compatibillity
-handle_pdu(Addr, Port, ReqId, SnmpResponse, UserPid) ->
- UserPid ! {handle_pdu, self(), Addr, Port, ReqId, SnmpResponse},
- ignore.
-
-
handle_trap(TargetName, SnmpTrap, UserPid) ->
UserPid ! {handle_trap, self(), TargetName, SnmpTrap},
ok.
-%% For backwards compatibillity
-handle_trap(Addr, Port, SnmpTrap, UserPid) ->
- UserPid ! {handle_trap, self(), Addr, Port, SnmpTrap},
- ok.
-
-
handle_inform(TargetName, SnmpInform, UserPid) ->
UserPid ! {handle_inform, self(), TargetName, SnmpInform},
receive
@@ -1015,26 +781,10 @@ handle_inform(TargetName, SnmpInform, UserPid) ->
ok
end.
-%% For backwards compatibillity
-handle_inform(Addr, Port, SnmpInform, UserPid) ->
- UserPid ! {handle_inform, self(), Addr, Port, SnmpInform},
- receive
- {handle_inform_no_response, {Addr, Port}} ->
- no_reply;
- {handle_inform_response, {Addr, Port}} ->
- ok
- end.
-
-
handle_report(TargetName, SnmpReport, UserPid) ->
UserPid ! {handle_report, self(), TargetName, SnmpReport},
ok.
-%% For backwards compatibillity
-handle_report(Addr, Port, SnmpReport, UserPid) ->
- UserPid ! {handle_report, self(), Addr, Port, SnmpReport},
- ok.
-
%%----------------------------------------------------------------------
%% Debug
diff --git a/lib/snmp/test/snmp_manager_user_old.erl b/lib/snmp/test/snmp_manager_user_old.erl
index 6280cef51f..9f951bf64d 100644
--- a/lib/snmp/test/snmp_manager_user_old.erl
+++ b/lib/snmp/test/snmp_manager_user_old.erl
@@ -107,10 +107,20 @@ unregister_agent(Addr, Port) ->
snmpm:unregister_agent(?USER_ID, Addr, Port).
agent_info(Addr, Port, Item) ->
- snmpm:agent_info(?USER_ID, Addr, Port, Item).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:agent_info(TargetName, Item);
+ Error ->
+ Error
+ end.
update_agent_info(Addr, Port, Item, Val) ->
- snmpm:update_agent_info(?USER_ID, Addr, Port, Item, Val).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:update_agent_info(?USER_ID, TargetName, Item, Val);
+ Error ->
+ Error
+ end.
which_agents() ->
snmpm:which_agents().
@@ -128,73 +138,153 @@ unload_mib(Mib) ->
%% --
sync_get(Addr, Oids) ->
- snmpm:g(?USER_ID, Addr, Oids).
+ case snmpm:target_name(Addr) of
+ {ok, TargetName} ->
+ snmpm:sync_get2(?USER_ID, TargetName, Oids);
+ Error ->
+ Error
+ end.
sync_get(Addr, Port, Oids) ->
- snmpm:g(?USER_ID, Addr, Port, Oids).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:sync_get2(?USER_ID, TargetName, Oids);
+ Error ->
+ Error
+ end.
%% --
async_get(Addr, Oids) ->
- snmpm:ag(?USER_ID, Addr, Oids).
+ case snmpm:target_name(Addr) of
+ {ok, TargetName} ->
+ snmpm:async_get2(?USER_ID, TargetName, Oids);
+ Error ->
+ Error
+ end.
async_get(Addr, Port, Oids) ->
- snmpm:ag(?USER_ID, Addr, Port, Oids).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:async_get2(?USER_ID, TargetName, Oids);
+ Error ->
+ Error
+ end.
%% --
sync_get_next(Addr, Oids) ->
- snmpm:gn(?USER_ID, Addr, Oids).
+ case snmpm:target_name(Addr) of
+ {ok, TargetName} ->
+ snmpm:sync_get_next2(?USER_ID, TargetName, Oids);
+ Error ->
+ Error
+ end.
sync_get_next(Addr, Port, Oids) ->
- snmpm:gn(?USER_ID, Addr, Port, Oids).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:sync_get_next2(?USER_ID, TargetName, Oids);
+ Error ->
+ Error
+ end.
%% --
async_get_next(Addr, Oids) ->
- snmpm:agn(?USER_ID, Addr, Oids).
+ case snmpm:target_name(Addr) of
+ {ok, TargetName} ->
+ snmpm:async_get_next2(?USER_ID, TargetName, Oids);
+ Error ->
+ Error
+ end.
async_get_next(Addr, Port, Oids) ->
- snmpm:agn(?USER_ID, Addr, Port, Oids).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:async_get_next2(?USER_ID, TargetName, Oids);
+ Error ->
+ Error
+ end.
%% --
sync_set(Addr, VAV) ->
- snmpm:s(?USER_ID, Addr, VAV).
+ case snmpm:target_name(Addr) of
+ {ok, TargetName} ->
+ snmpm:sync_set2(?USER_ID, TargetName, VAV);
+ Error ->
+ Error
+ end.
sync_set(Addr, Port, VAV) ->
- snmpm:s(?USER_ID, Addr, Port, VAV).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:sync_set2(?USER_ID, TargetName, VAV);
+ Error ->
+ Error
+ end.
%% --
async_set(Addr, VAV) ->
- snmpm:as(?USER_ID, Addr, VAV).
+ case snmpm:target_name(Addr) of
+ {ok, TargetName} ->
+ snmpm:async_set2(?USER_ID, TargetName, VAV);
+ Error ->
+ Error
+ end.
async_set(Addr, Port, VAV) ->
- snmpm:as(?USER_ID, Addr, Port, VAV).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:async_set2(?USER_ID, TargetName, VAV);
+ Error ->
+ Error
+ end.
%% --
sync_get_bulk(Addr, NonRep, MaxRep, Oids) ->
- snmpm:gb(?USER_ID, Addr, NonRep, MaxRep, Oids).
+ case snmpm:target_name(Addr) of
+ {ok, TargetName} ->
+ snmpm:sync_get_bulk2(?USER_ID, TargetName, NonRep, MaxRep, Oids);
+ Error ->
+ Error
+ end.
sync_get_bulk(Addr, Port, NonRep, MaxRep, Oids) ->
- snmpm:gb(?USER_ID, Addr, Port, NonRep, MaxRep, Oids).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:sync_get_bulk2(?USER_ID, TargetName, NonRep, MaxRep, Oids);
+ Error ->
+ Error
+ end.
%% --
async_get_bulk(Addr, NonRep, MaxRep, Oids) ->
- snmpm:agb(?USER_ID, Addr, NonRep, MaxRep, Oids).
+ case snmpm:target_name(Addr) of
+ {ok, TargetName} ->
+ snmpm:async_get_bulk2(?USER_ID, TargetName, NonRep, MaxRep, Oids);
+ Error ->
+ Error
+ end.
async_get_bulk(Addr, Port, NonRep, MaxRep, Oids) ->
- snmpm:agb(?USER_ID, Addr, Port, NonRep, MaxRep, Oids).
+ case snmpm:target_name(Addr, Port) of
+ {ok, TargetName} ->
+ snmpm:async_get_bulk2(?USER_ID, TargetName, NonRep, MaxRep, Oids);
+ Error ->
+ Error
+ end.
%% --
diff --git a/lib/snmp/test/snmp_manager_user_test.erl b/lib/snmp/test/snmp_manager_user_test.erl
index fefa1ad713..41d5c50b19 100644
--- a/lib/snmp/test/snmp_manager_user_test.erl
+++ b/lib/snmp/test/snmp_manager_user_test.erl
@@ -36,7 +36,7 @@
%% -compile(export_all).
-export([
-all/0,groups/0,init_per_group/2,end_per_group/2,
+ all/0,groups/0,init_per_group/2,end_per_group/2,
init_per_testcase/2, end_per_testcase/2,
diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl
index e327456bc4..f0abae73e8 100644
--- a/lib/snmp/test/snmp_test_lib.erl
+++ b/lib/snmp/test/snmp_test_lib.erl
@@ -324,7 +324,7 @@ fail(Reason, Mod, Line) ->
skip(Reason, Module, Line) ->
String = lists:flatten(io_lib:format("Skipping ~p(~p): ~p~n",
[Module, Line, Reason])),
- exit({skipped, String}).
+ exit({skip, String}).
%% ----------------------------------------------------------------
diff --git a/lib/snmp/test/snmp_test_manager.erl b/lib/snmp/test/snmp_test_manager.erl
index 4cc6d36acc..0df2350d58 100644
--- a/lib/snmp/test/snmp_test_manager.erl
+++ b/lib/snmp/test/snmp_test_manager.erl
@@ -43,7 +43,7 @@
%% Manager callback API:
-export([
handle_error/3,
- handle_agent/4,
+ handle_agent/5,
handle_pdu/4,
handle_trap/3,
handle_inform/3,
@@ -239,7 +239,7 @@ handle_info({snmp_error, ReqId, Reason},
P ! {snmp_error, ReqId, Reason},
{noreply, State};
-handle_info({snmp_agent, Addr, Port, Info, Pid},
+handle_info({snmp_agent, Addr, Port, Info, Pid, _UserData},
#state{parent = P} = State) ->
error_msg("detected new agent: "
"~n Addr: ~w"
@@ -326,8 +326,8 @@ handle_error(ReqId, Reason, Pid) ->
ignore.
-handle_agent(Addr, Port, SnmpInfo, Pid) ->
- Pid ! {snmp_agent, Addr, Port, SnmpInfo, self()},
+handle_agent(Addr, Port, SnmpInfo, Pid, UserData) ->
+ Pid ! {snmp_agent, Addr, Port, SnmpInfo, self(), UserData},
receive
{snmp_agent_reply, Reply, Pid} ->
Reply
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index b90dbe4eef..8145e415f3 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 4.22.1
+SNMP_VSN = 4.23
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 517cbf1ef9..a0afb5056e 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -181,10 +181,13 @@
(simply passed on to the transport protocol).</p></item>
<tag><c><![CDATA[{ipv6_disabled, boolean()}]]></c></tag>
<item>
- <p>Determines if SSH shall use IPv6 or not.</p></item>
- <tag><c><![CDATA[{idle_time, timeout()}]]></c></tag>
+ <p>Determines if SSH shall use IPv6 or not.</p>
+ </item>
+ <tag><c><![CDATA[{rekey_limit, integer()}]]></c></tag>
<item>
- <p>Sets a timeout on connection when no channels are active, default is infinity</p></item>
+ <p>Provide, in bytes, when rekeying should be initiated,
+ defaults to one time each GB and one time per hour.</p>
+ </item>
</taglist>
</desc>
</func>
diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml
index a4273195b5..3666bc7692 100644
--- a/lib/ssh/doc/src/ssh_sftpd.xml
+++ b/lib/ssh/doc/src/ssh_sftpd.xml
@@ -80,7 +80,12 @@
the user will end up in <c>/tmp/etc</c>.
</p>
</item>
- </taglist>
+ <tag><c><![CDATA[{sftpd_vsn, integer()}]]></c></tag>
+ <item>
+ <p>Sets the sftp version to use, defaults to 5. Version 6 is under
+ development and limited.</p>
+ </item>
+ </taglist>
</desc>
</func>
</funcs>
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index 1a54f3f964..87b811d591 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -5,6 +5,7 @@
<header>
<copyright>
<year>2012</year>
+ <year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -102,7 +103,8 @@
<p>Use the openssh client from a shell to connect to the Erlang ssh daemon.</p>
<code>
- $bash> ssh tarlop -p 8989 -i /tmp/otptest_user/.ssh/id_rsa -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts
+ $bash> ssh tarlop -p 8989 -i /tmp/otptest_user/.ssh/id_rsa\
+ -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts
The authenticity of host 'tarlop' can't be established.
RSA key fingerprint is 14:81:80:50:b1:1f:57:dd:93:a8:2d:2f:dd:90:ae:a8.
Are you sure you want to continue connecting (yes/no)? yes
@@ -174,8 +176,9 @@
<code type="erl" >
1> ssh:start().
ok
- 2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"}, {user_dir, "/tmp/otptest_user/.ssh"},
- {subsystems, [ssh_sftpd:subsystem_spec([{cwd, "/tmp/sftp/example"}])]}]).
+ 2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
+ {user_dir, "/tmp/otptest_user/.ssh"},
+ {subsystems, [ssh_sftpd:subsystem_spec([{cwd, "/tmp/sftp/example"}])]}]).
{ok,&lt;0.54.0>}
3>
</code>
@@ -183,7 +186,8 @@
<p> Run the openssh sftp client</p>
<code type="erl">
- $bash> sftp -oPort=8989 -o IdentityFile=/tmp/otptest_user/.ssh/id_rsa -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts tarlop
+ $bash> sftp -oPort=8989 -o IdentityFile=/tmp/otptest_user/.ssh/id_rsa\
+ -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts tarlop
Connecting to tarlop...
sftp> pwd
Remote working directory: /tmp/sftp/example
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
index 6ba32e018f..826a11f1f4 100644
--- a/lib/ssh/src/ssh.appup.src
+++ b/lib/ssh/src/ssh.appup.src
@@ -19,29 +19,15 @@
{"%VSN%",
[
- {<<"2.1.1">>, [{restart_application, ssh}]},
- {<<"2.1">>, [{load_module, ssh_sftpd_file_api, soft_purge, soft_purge, []},
- {load_module, ssh_connection, soft_purge, soft_purge, []},
- {load_module, ssh_connection_manager, soft_purge, soft_purge, []},
- {load_module, ssh_auth, soft_purge, soft_purge, []},
- {load_module, ssh_connection_handler, soft_purge, soft_purge, []},
- {load_module, ssh_channel, soft_purge, soft_purge, []},
- {load_module, ssh_file, soft_purge, soft_purge, []}]},
- {load_module, ssh, soft_purge, soft_purge, []}]},
+ {<<"2.1.1">>, [{restart_application, ssh}]},
+ {<<"2.1">>, [{restart_application, ssh}]},
{<<"2.0\\.*">>, [{restart_application, ssh}]},
{<<"1\\.*">>, [{restart_application, ssh}]}
],
[
{<<"2.1.1">>, [{restart_application, ssh}]},
- {<<"2.1">>,[{load_module, ssh_sftpd_file_api, soft_purge, soft_purge, []},
- {load_module, ssh_connection, soft_purge, soft_purge, []},
- {load_module, ssh_connection_manager, soft_purge, soft_purge, []},
- {load_module, ssh_auth, soft_purge, soft_purge, []},
- {load_module, ssh_connection_handler, soft_purge, soft_purge, []},
- {load_module, ssh_channel, soft_purge, soft_purge, []},
- {load_module, ssh_file, soft_purge, soft_purge, []}]},
- {load_module, ssh, soft_purge, soft_purge, []}]},
+ {<<"2.1">>,[{restart_application, ssh}]},
{<<"2.0\\.*">>, [{restart_application, ssh}]},
{<<"1\\.*">>, [{restart_application, ssh}]}
]
-}. \ No newline at end of file
+}.
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index a3ba8148eb..3ef26b1678 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -369,6 +369,8 @@ handle_option([{quiet_mode, _} = Opt|Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([{idle_time, _} = Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
+handle_option([{rekey_limit, _} = Opt|Rest], SocketOptions, SshOptions) ->
+ handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);
handle_option([Opt | Rest], SocketOptions, SshOptions) ->
handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions).
@@ -449,6 +451,8 @@ handle_ssh_option({quiet_mode, Value} = Opt) when Value == true;
Opt;
handle_ssh_option({idle_time, Value} = Opt) when is_integer(Value), Value > 0 ->
Opt;
+handle_ssh_option({rekey_limit, Value} = Opt) when is_integer(Value) ->
+ Opt;
handle_ssh_option(Opt) ->
throw({error, {eoptions, Opt}}).
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index b79e8530b7..88b45111ff 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -35,7 +35,8 @@
-export([start_link/4, send/2, renegotiate/1, send_event/2,
connection_info/3,
- peer_address/1]).
+ peer_address/1,
+ renegotiate_data/1]).
%% gen_fsm callbacks
-export([hello/2, kexinit/2, key_exchange/2, new_keys/2,
@@ -85,6 +86,8 @@ send(ConnectionHandler, Data) ->
renegotiate(ConnectionHandler) ->
send_all_state_event(ConnectionHandler, renegotiate).
+renegotiate_data(ConnectionHandler) ->
+ send_all_state_event(ConnectionHandler, data_size).
connection_info(ConnectionHandler, From, Options) ->
send_all_state_event(ConnectionHandler, {info, From, Options}).
@@ -500,7 +503,22 @@ handle_event(renegotiate, StateName, State) ->
handle_event({info, From, Options}, StateName, #state{ssh_params = Ssh} = State) ->
spawn(?MODULE, ssh_info_handler, [Options, Ssh, From]),
{next_state, StateName, State};
-
+handle_event(data_size, connected, #state{ssh_params = Ssh0} = State) ->
+ Sent = inet:getstat(State#state.socket, [send_oct]),
+ MaxSent = proplists:get_value(rekey_limit, State#state.opts, 1024000000),
+ case Sent >= MaxSent of
+ true ->
+ {KeyInitMsg, SshPacket, Ssh} = ssh_transport:key_exchange_init_msg(Ssh0),
+ send_msg(SshPacket, State),
+ {next_state, connected,
+ next_packet(State#state{ssh_params = Ssh,
+ key_exchange_init_msg = KeyInitMsg,
+ renegotiate = true})};
+ _ ->
+ {next_state, connected, next_packet(State)}
+ end;
+handle_event(data_size, StateName, State) ->
+ {next_state, StateName, State};
handle_event({unknown, Data}, StateName, State) ->
Msg = #ssh_msg_unimplemented{sequence = Data},
send_msg(Msg, State),
diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl
index 0c1eee5186..94a9ed505f 100644
--- a/lib/ssh/src/ssh_connection_manager.erl
+++ b/lib/ssh/src/ssh_connection_manager.erl
@@ -125,7 +125,8 @@ info(ConnectionManager, ChannelProcess) ->
%% or amount of data sent counter!
renegotiate(ConnectionManager) ->
cast(ConnectionManager, renegotiate).
-
+renegotiate_data(ConnectionManager) ->
+ cast(ConnectionManager, renegotiate_data).
connection_info(ConnectionManager, Options) ->
call(ConnectionManager, {connection_info, Options}).
@@ -481,7 +482,9 @@ handle_cast({global_request, _, _, _, _} = Request, State0) ->
handle_cast(renegotiate, #state{connection = Pid} = State) ->
ssh_connection_handler:renegotiate(Pid),
{noreply, State};
-
+handle_cast(renegotiate_data, #state{connection = Pid} = State) ->
+ ssh_connection_handler:renegotiate_data(Pid),
+ {noreply, State};
handle_cast({adjust_window, ChannelId, Bytes},
#state{connection = Pid, connection_state =
#connection{channel_cache = Cache}} = State) ->
@@ -520,6 +523,8 @@ handle_info({start_connection, server,
Exec = proplists:get_value(exec, Options),
CliSpec = proplists:get_value(ssh_cli, Options, {ssh_cli, [Shell]}),
ssh_connection_handler:send_event(Connection, socket_control),
+ erlang:send_after(3600000, self(), rekey),
+ erlang:send_after(60000, self(), rekey_data),
{noreply, State#state{connection = Connection,
connection_state =
CState#connection{address = Address,
@@ -536,6 +541,8 @@ handle_info({start_connection, client,
case (catch ssh_transport:connect(Parent, Address,
Port, SocketOpts, Options)) of
{ok, Connection} ->
+ erlang:send_after(60000, self(), rekey_data),
+ erlang:send_after(3600000, self(), rekey),
{noreply, State#state{connection = Connection}};
Reason ->
Pid ! {self(), not_connected, Reason},
@@ -568,8 +575,15 @@ handle_info({'DOWN', _Ref, process, ChannelPid, _Reason}, State) ->
%%% So that terminate will be run when supervisor is shutdown
handle_info({'EXIT', _Sup, Reason}, State) ->
- {stop, Reason, State}.
-
+ {stop, Reason, State};
+handle_info(rekey, State) ->
+ renegotiate(self()),
+ erlang:send_after(3600000, self(), rekey),
+ {noreply, State};
+handle_info(rekey_data, State) ->
+ renegotiate_data(self()),
+ erlang:send_after(60000, self(), rekey_data),
+ {noreply, State}.
handle_password(Opts) ->
handle_rsa_password(handle_dsa_password(handle_normal_password(Opts))).
handle_normal_password(Opts) ->
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 6d6f4a0121..c7e8373840 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -119,9 +119,7 @@ init(Options) ->
{Root0, State0}
end,
MaxLength = proplists:get_value(max_files, Options, 0),
-
- Vsn = proplists:get_value(vsn, Options, 5),
-
+ Vsn = proplists:get_value(sftpd_vsn, Options, 5),
{ok, State#state{cwd = CWD, root = Root, max_files = MaxLength,
handles = [], pending = <<>>,
xf = #ssh_xfer{vsn = Vsn, ext = []}}}.
@@ -361,17 +359,21 @@ handle_op(?SSH_FXP_FSETSTAT, ReqId, <<?UINT32(HLen), BinHandle:HLen/binary,
State0
end;
handle_op(?SSH_FXP_REMOVE, ReqId, <<?UINT32(PLen), BPath:PLen/binary>>,
- State0 = #state{file_handler = FileMod, file_state = FS0}) ->
+ State0 = #state{file_handler = FileMod, file_state = FS0, xf = #ssh_xfer{vsn = Vsn}}) ->
Path = relate_file_name(BPath, State0),
- %% case FileMod:is_dir(Path) of %% This version 6 we still have ver 5
- %% true ->
- %% ssh_xfer:xf_send_status(State#state.xf, ReqId,
- %% ?SSH_FX_FILE_IS_A_DIRECTORY);
- %% false ->
- {Status, FS1} = FileMod:delete(Path, FS0),
- State1 = State0#state{file_state = FS1},
- send_status(Status, ReqId, State1);
- %%end;
+ {IsDir, _FS1} = FileMod:is_dir(Path, FS0),
+ case IsDir of %% This version 6 we still have ver 5
+ true when Vsn > 5 ->
+ ssh_xfer:xf_send_status(State0#state.xf, ReqId,
+ ?SSH_FX_FILE_IS_A_DIRECTORY, "File is a directory");
+ true ->
+ ssh_xfer:xf_send_status(State0#state.xf, ReqId,
+ ?SSH_FX_FAILURE, "File is a directory");
+ false ->
+ {Status, FS1} = FileMod:delete(Path, FS0),
+ State1 = State0#state{file_state = FS1},
+ send_status(Status, ReqId, State1)
+ end;
handle_op(?SSH_FXP_RMDIR, ReqId, <<?UINT32(PLen), BPath:PLen/binary>>,
State0 = #state{file_handler = FileMod, file_state = FS0}) ->
Path = relate_file_name(BPath, State0),
@@ -629,31 +631,34 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
do_open(ReqId, State, Path, Flags).
do_open(ReqId, State0, Path, Flags) ->
- #state{file_handler = FileMod, file_state = FS0, root = Root} = State0,
+ #state{file_handler = FileMod, file_state = FS0, root = Root, xf = #ssh_xfer{vsn = Vsn}} = State0,
XF = State0#state.xf,
F = [binary | Flags],
- %% case FileMod:is_dir(Path) of %% This is version 6 we still have 5
- %% true ->
- %% ssh_xfer:xf_send_status(State#state.xf, ReqId,
- %% ?SSH_FX_FILE_IS_A_DIRECTORY);
- %% false ->
-
- AbsPath = case Root of
- "" ->
- Path;
- _ ->
- relate_file_name(Path, State0)
- end,
-
- {Res, FS1} = FileMod:open(AbsPath, F, FS0),
- State1 = State0#state{file_state = FS1},
- case Res of
- {ok, IoDevice} ->
- add_handle(State1, XF, ReqId, file, {Path,IoDevice});
- {error, Error} ->
- ssh_xfer:xf_send_status(State1#state.xf, ReqId,
- ssh_xfer:encode_erlang_status(Error)),
- State1
+ {IsDir, _FS1} = FileMod:is_dir(Path, FS0),
+ case IsDir of
+ true when Vsn > 5 ->
+ ssh_xfer:xf_send_status(State0#state.xf, ReqId,
+ ?SSH_FX_FILE_IS_A_DIRECTORY, "File is a directory");
+ true ->
+ ssh_xfer:xf_send_status(State0#state.xf, ReqId,
+ ?SSH_FX_FAILURE, "File is a directory");
+ false ->
+ AbsPath = case Root of
+ "" ->
+ Path;
+ _ ->
+ relate_file_name(Path, State0)
+ end,
+ {Res, FS1} = FileMod:open(AbsPath, F, FS0),
+ State1 = State0#state{file_state = FS1},
+ case Res of
+ {ok, IoDevice} ->
+ add_handle(State1, XF, ReqId, file, {Path,IoDevice});
+ {error, Error} ->
+ ssh_xfer:xf_send_status(State1#state.xf, ReqId,
+ ssh_xfer:encode_erlang_status(Error)),
+ State1
+ end
end.
%% resolve all symlinks in a path
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index d5b6dd03d1..4dfd9ed8b0 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -383,6 +383,8 @@ decode_status(Status) ->
?SSH_FX_UNKNOWN_PRINCIPLE -> unknown_principle;
?SSH_FX_LOCK_CONFlICT -> lock_conflict;
?SSH_FX_NOT_A_DIRECTORY -> not_a_directory;
+ ?SSH_FX_FILE_IS_A_DIRECTORY -> file_is_a_directory;
+ ?SSH_FX_CANNOT_DELETE -> cannot_delete;
_ -> {error,Status}
end.
@@ -392,6 +394,9 @@ encode_erlang_status(Status) ->
eof -> ?SSH_FX_EOF;
enoent -> ?SSH_FX_NO_SUCH_FILE;
eacces -> ?SSH_FX_PERMISSION_DENIED;
+ eisdir -> ?SSH_FX_FILE_IS_A_DIRECTORY;
+ eperm -> ?SSH_FX_CANNOT_DELETE;
+ eexist -> ?SSH_FX_FILE_ALREADY_EXISTS;
_ -> ?SSH_FX_FAILURE
end.
diff --git a/lib/ssh/src/ssh_xfer.hrl b/lib/ssh/src/ssh_xfer.hrl
index c13950eb6e..0d85cf2094 100644
--- a/lib/ssh/src/ssh_xfer.hrl
+++ b/lib/ssh/src/ssh_xfer.hrl
@@ -58,7 +58,6 @@
%%% # SSH_FX_xxx
%%% Description: Response packet types for file transfer protocol.
%%%----------------------------------------------------------------------
-
-define(SSH_FX_OK, 0).
-define(SSH_FX_EOF, 1).
-define(SSH_FX_NO_SUCH_FILE, 2).
@@ -79,7 +78,18 @@
-define(SSH_FX_LOCK_CONFlICT, 17).
-define(SSH_FX_DIR_NOT_EMPTY, 18).
-define(SSH_FX_NOT_A_DIRECTORY, 19).
+-define(SSH_FX_INVALID_FILENAME, 20).
+-define(SSH_FX_LINK_LOOP, 21).
+-define(SSH_FX_CANNOT_DELETE, 22).
+-define(SSH_FX_INVALID_PARAMETER, 23).
-define(SSH_FX_FILE_IS_A_DIRECTORY, 24).
+-define(SSH_FX_BYTE_RANGE_LOCK_CONFLICT,25).
+-define(SSH_FX_BYTE_RANGE_LOCK_REFUSED, 26).
+-define(SSH_FX_DELETE_PENDING, 27).
+-define(SSH_FX_FILE_CORRUPT, 28).
+-define(SSH_FX_OWNER_INVALID, 29).
+-define(SSH_FX_GROUP_INVALID, 30).
+-define(SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK,31).
%%%----------------------------------------------------------------------
%%% # SSH_FILEXFER_xxx
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 5fec7f0cd7..efcb11f88f 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -42,15 +42,14 @@ all() ->
{group, dsa_pass_key},
{group, rsa_pass_key},
{group, internal_error},
- {group, idle_time},
daemon_already_started,
server_password_option,
server_userpassword_option,
close].
groups() ->
- [{dsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time]},
- {rsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time]},
+ [{dsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey]},
+ {rsa_key, [], [send, exec, exec_compressed, shell, known_hosts, idle_time, rekey]},
{dsa_pass_key, [], [pass_phrase]},
{rsa_pass_key, [], [pass_phrase]},
{internal_error, [], [internal_error]}
@@ -247,7 +246,8 @@ idle_time(Config) ->
ConnectionRef =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user_dir, UserDir},
- {user_interaction, false}]),
+ {user_interaction, false},
+ {idle_time, 2000}]),
{ok, Id} = ssh_connection:session_channel(ConnectionRef, 1000),
ssh_connection:close(ConnectionRef, Id),
receive
@@ -256,6 +256,28 @@ idle_time(Config) ->
end,
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
+rekey(doc) ->
+ ["Idle timeout test"];
+rekey(Config) ->
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2},
+ {rekey_limit, 0}]),
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user_interaction, false},
+ {rekey_limit, 0}]),
+ receive
+ after 15000 ->
+ %%By this time rekeying would have been done
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid)
+ end.
+%%--------------------------------------------------------------------
shell(doc) ->
["Test that ssh:shell/2 works"];
shell(Config) when is_list(Config) ->
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index b995eb9f0e..5aa46872ee 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -58,7 +58,8 @@ all() ->
links,
ver3_rename,
relpath,
- sshd_read_file].
+ sshd_read_file,
+ ver6_basic].
groups() ->
[].
@@ -106,12 +107,18 @@ init_per_testcase(TestCase, Config) ->
SystemDir = filename:join(?config(priv_dir, Config), system),
Port = ssh_test_lib:inet_port(node()),
-
- {ok, Sftpd} =
- ssh_sftpd:listen(Port, [{system_dir, SystemDir},
- {user_dir, PrivDir},
- {user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end}]),
+ Options = [{system_dir, SystemDir},
+ {user_dir, PrivDir},
+ {user_passwords,[{?USER, ?PASSWD}]},
+ {pwdfun, fun(_,_) -> true end}],
+ {ok, Sftpd} = case TestCase of
+ ver6_basic ->
+ SubSystems = [ssh_sftpd:subsystem_spec([{sftpd_vsn, 6}])],
+ ssh:daemon(Port, [{subsystems, SubSystems}|Options]);
+ _ ->
+ SubSystems = [ssh_sftpd:subsystem_spec([])],
+ ssh:daemon(Port, [{subsystems, SubSystems}|Options])
+ end,
Cm = ssh_test_lib:connect(Port,
[{user_dir, ClientUserDir},
@@ -341,7 +348,7 @@ mk_rm_dir(Config) when is_list(Config) ->
_/binary>>, _} = mkdir(DirName, Cm, Channel, ReqId),
NewReqId = 1,
- {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId), ?UINT32(?SSH_FX_FAILURE),
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId), ?UINT32(?SSH_FX_FILE_ALREADY_EXISTS),
_/binary>>, _} = mkdir(DirName, Cm, Channel, NewReqId),
NewReqId1 = 2,
@@ -591,7 +598,18 @@ sshd_read_file(Config) when is_list(Config) ->
read_file(Handle, 100, 0, Cm, Channel, NewReqId),
{ok, Data} = file:read_file(FileName).
-
+ver6_basic(doc) ->
+ ["Test SFTP Version 6"];
+ver6_basic(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ %FileName = filename:join(PrivDir, "test.txt"),
+ {Cm, Channel} = ?config(sftp, Config),
+ ReqId = 0,
+ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId), % Ver 6 we have 5
+ ?UINT32(?SSH_FX_FILE_IS_A_DIRECTORY), _/binary>>, _} =
+ open_file(PrivDir, Cm, Channel, ReqId,
+ ?ACE4_READ_DATA bor ?ACE4_READ_ATTRIBUTES,
+ ?SSH_FXF_OPEN_EXISTING).
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
index 7fc2312661..8f722941d4 100644
--- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
@@ -42,7 +42,8 @@ all() ->
quit,
file_cb,
root_dir,
- list_dir_limited].
+ list_dir_limited,
+ ver6_basic].
groups() ->
[].
@@ -112,7 +113,12 @@ init_per_testcase(TestCase, Config) ->
[{system_dir, SystemDir},
{user_dir, PrivDir},
{subsystems, [Spec]}];
-
+ "ver6_basic" ->
+ Spec =
+ ssh_sftpd:subsystem_spec([{sftpd_vsn, 6}]),
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
+ {subsystems, [Spec]}];
_ ->
[{user_dir, PrivDir},
{system_dir, SystemDir}]
@@ -232,7 +238,7 @@ file_cb(Config) when is_list(Config) ->
NewDir = filename:join(PrivDir, "testdir"),
ok = ssh_sftp:make_dir(Sftp, NewDir),
alt_file_handler_check(alt_make_dir),
-
+
ok = ssh_sftp:del_dir(Sftp, NewDir),
alt_file_handler_check(alt_read_link_info),
alt_file_handler_check(alt_write_file_info),
@@ -260,6 +266,15 @@ list_dir_limited(Config) when is_list(Config) ->
ssh_sftp:list_dir(Sftp, "."),
ct:pal("Listing: ~p~n", [Listing]).
+ver6_basic(doc) ->
+ ["Test some version 6 features"];
+ver6_basic(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ NewDir = filename:join(PrivDir, "testdir2"),
+ {Sftp, _} = ?config(sftp, Config),
+ ok = ssh_sftp:make_dir(Sftp, NewDir),
+ %%Test file_is_a_directory
+ {error, file_is_a_directory} = ssh_sftp:delete(Sftp, NewDir).
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl
index 9e119c4929..9f8a7c496c 100644
--- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_sftpd_file_alt.erl
@@ -48,7 +48,7 @@ get_cwd(State) ->
{file:get_cwd(), State}.
is_dir(AbsPath, State) ->
- sftpd_file_alt_tester ! alt_is_dir,
+ %sftpd_file_alt_tester ! alt_is_dir,
{filelib:is_dir(AbsPath), State}.
list_dir(AbsPath, State) ->
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index f0eac76264..e45a4c774f 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -36,8 +36,8 @@
<list type="bulleted">
<item>ssl requires the crypto and public_key applications.</item>
- <item>Supported SSL/TLS-versions are SSL-3.0 and TLS-1.0, experimental
- support for TLS-1.1 and TLS-1.2 is also available (no support for elliptic curve cipher suites yet).</item>
+ <item>Supported SSL/TLS-versions are SSL-3.0, TLS-1.0,
+ TLS-1.1 and TLS-1.2 (no support for elliptic curve cipher suites yet).</item>
<item>For security reasons sslv2 is not supported.</item>
<item>Ephemeral Diffie-Hellman cipher suites are supported
but not Diffie Hellman Certificates cipher suites.</item>
diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml
index 2ba6f48611..178bbcaebb 100644
--- a/lib/ssl/doc/src/ssl_app.xml
+++ b/lib/ssl/doc/src/ssl_app.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE appref SYSTEM "appref.dtd">
<appref>
@@ -29,7 +29,17 @@
sockets.</appsummary>
<section>
- <title>Environment</title>
+ <title>DEPENDENCIES</title>
+ <p>The ssl application uses the Erlang applications public_key and
+ crypto to handle public keys and encryption, hence these
+ applications needs to be loaded for the ssl application to work. In
+ an embedded environment that means they need to be started with
+ application:start/[1,2] before the ssl application is started.
+ </p>
+ </section>
+
+ <section>
+ <title>ENVIRONMENT</title>
<p>The following application environment configuration parameters
are defined for the SSL application. Refer to application(3) for
more information about configuration parameters.
diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml
index 17268a634d..f540dc999b 100644
--- a/lib/ssl/doc/src/ssl_protocol.xml
+++ b/lib/ssl/doc/src/ssl_protocol.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2011</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -25,9 +25,8 @@
<file>ssl_protocol.xml</file>
</header>
- <p>The erlang SSL application currently supports SSL 3.0 and TLS 1.0
- RFC 2246, and will in the future also support later versions of TLS.
- SSL 2.0 is not supported.
+ <p>The erlang SSL application currently implements the protocol SSL/TLS
+ for currently supported versions see <seealso marker="ssl">ssl(3)</seealso>
</p>
<p>By default erlang SSL is run over the TCP/IP protocol even
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 6224334a6e..09f2819ca8 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -28,14 +28,11 @@
cipher_suites/0, cipher_suites/1, suite_definition/1,
close/1, shutdown/2,
connect/3, connect/2, connect/4, connection_info/1,
- controlling_process/2, listen/2, pid/1, peername/1, peercert/1,
+ controlling_process/2, listen/2, peername/1, peercert/1,
recv/2, recv/3, send/2, getopts/2, setopts/2, sockname/1,
versions/0, session_info/1, format_error/1,
renegotiate/1, prf/5, clear_pem_cache/0, random_bytes/1, negotiated_next_protocol/1]).
-
--deprecated({pid, 1, next_major_release}).
-
-include("ssl_internal.hrl").
-include("ssl_record.hrl").
-include("ssl_cipher.hrl").
@@ -956,12 +953,3 @@ make_next_protocol_selector({server, AllProtocols, DefaultProtocol}) ->
PreferredProtocol -> PreferredProtocol
end
end.
-
-%% Only used to remove exit messages from old ssl
-%% First is a nonsense clause to provide some
-%% backward compatibility for orber that uses this
-%% function in a none recommended way, but will
-%% work correctly if a valid pid is returned.
-%% Deprcated to be removed in r16
-pid(#sslsocket{})->
- whereis(ssl_connection_sup).
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index a5db2dcee7..ed0dc34adf 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -69,8 +69,8 @@
-define(TRUE, 0).
-define(FALSE, 1).
--define(DEFAULT_SUPPORTED_VERSIONS, [tlsv1, sslv3]). %% Add 'tlsv1.1' in R16
-define(ALL_SUPPORTED_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1, sslv3]).
+-define(MIN_SUPPORTED_VERSIONS, ['tlsv1.1', tlsv1, sslv3]).
-record(ssl_options, {
versions, % 'tlsv1.2' | 'tlsv1.1' | tlsv1 | sslv3
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 8e93ce4634..173b9611c6 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -463,10 +463,9 @@ supported_protocol_versions() ->
supported_protocol_versions([]) ->
Vsns = case sufficient_tlsv1_2_crypto_support() of
true ->
- %%?ALL_SUPPORTED_VERSIONS; %% Add TlS-1.2 as default in R16
- ?DEFAULT_SUPPORTED_VERSIONS;
+ ?ALL_SUPPORTED_VERSIONS;
false ->
- ?DEFAULT_SUPPORTED_VERSIONS
+ ?MIN_SUPPORTED_VERSIONS
end,
application:set_env(ssl, protocol_version, Vsns),
Vsns;
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index f4e19b3f87..107220c335 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -106,8 +106,8 @@ init_per_testcase(TestCase, Config0) ->
special_init(TestCase, Config)
when TestCase == erlang_client_openssl_server_renegotiate;
- TestCase == erlang_client_openssl_server_no_wrap_sequence_number;
- TestCase == erlang_server_openssl_client_no_wrap_sequence_number
+ TestCase == erlang_client_openssl_server_nowrap_seqnum;
+ TestCase == erlang_server_openssl_client_nowrap_seqnum
->
check_sane_openssl_renegotaite(Config);
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 50f6427eaa..6f1e61e70c 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -101,7 +101,6 @@ XML_REF6_FILES = stdlib_app.xml
XML_PART_FILES = part.xml part_notes.xml part_notes_history.xml
XML_CHAPTER_FILES = io_protocol.xml unicode_usage.xml notes.xml notes_history.xml
-GIF_FILES = ushell1.gif ushell2.gif ushell3.gif
BOOK_FILES = book.xml
@@ -112,8 +111,7 @@ XML_FILES = \
# ----------------------------------------------------
HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(GIF_FILES:%.gif=$(HTMLDIR)/%.gif)
+ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
INFO_FILE = ../../info
@@ -138,21 +136,16 @@ SPECS_FLAGS = -I../../include -I../../../kernel/include
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
docs: man pdf html
$(TOP_PDF_FILE): $(XML_FILES)
pdf: $(TOP_PDF_FILE)
-html: gifs $(HTML_REF_MAN_FILE)
+html: $(HTML_REF_MAN_FILE)
man: $(MAN3_FILES) $(MAN6_FILES)
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
debug opt:
clean clean_docs:
diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml
index 386ed89fe1..3e8aba2e5f 100644
--- a/lib/stdlib/doc/src/epp.xml
+++ b/lib/stdlib/doc/src/epp.xml
@@ -37,6 +37,18 @@
<p>The Erlang code preprocessor includes functions which are used
by <c>compile</c> to preprocess macros and include files before
the actual parsing takes place.</p>
+ <p>The Erlang source file <marker
+ id="encoding"><em>encoding</em></marker> is selected by a
+ comment in one of the first two lines of the source file. The
+ first string that matches the regular expression
+ <c>coding\s*[:=]\s*([-a-zA-Z0-9])+</c> selects the encoding. If
+ the matching string is not a valid encoding it is ignored. The
+ valid encodings are <c>Latin-1</c> and <c>UTF-8</c> where the
+ case of the characters can be chosen freely. Examples:</p>
+ <pre>
+%% coding: utf-8
+%% For this file we have chosen encoding = Latin-1
+%% -*- coding: latin-1 -*-</pre>
</description>
<datatypes>
<datatype>
@@ -46,6 +58,9 @@
<name name="epp_handle"></name>
<desc><p>Handle to the epp server.</p></desc>
</datatype>
+ <datatype>
+ <name name="source_encoding"></name>
+ </datatype>
</datatypes>
<funcs>
<func>
@@ -83,6 +98,50 @@
</desc>
</func>
<func>
+ <name name="default_encoding" arity="0"/>
+ <fsummary>Return the default encoding of Erlang source files</fsummary>
+ <desc>
+ <p>Returns the default encoding of Erlang source files.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="encoding_to_string" arity="1"/>
+ <fsummary>Return a string representation of an encoding</fsummary>
+ <desc>
+ <p>Returns a string representation of an encoding. The string
+ is recognized by <c>read_encoding/1,2</c> and
+ <c>set_encoding/1</c> as a valid encoding.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="read_encoding" arity="1"/>
+ <name name="read_encoding" arity="2"/>
+ <fsummary>Read the encoding from a file</fsummary>
+ <desc>
+ <p>Read the <seealso marker="#encoding">encoding</seealso> from
+ a file. Returns the read encoding, or <c>none</c> if no
+ valid encoding was found.</p>
+ <p>The option <c>in_comment_only</c> is <c>true</c> by
+ default, which is correct for Erlang source files. If set to
+ <c>false</c> the encoding string does not necessarily have to
+ occur in a comment.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="set_encoding" arity="1"/>
+ <fsummary>Read and set the encoding of an IO device</fsummary>
+ <desc>
+ <p>Reads the <seealso marker="#encoding">encoding</seealso> from
+ an IO device and sets the encoding of the device
+ accordingly. The position of the IO device referenced by
+ <c><anno>File</anno></c> is not affected. If no valid
+ encoding can be read from the IO device the encoding of the
+ IO device is set to the default encoding.</p>
+ <p>Returns the read encoding, or <c>none</c> if no valid
+ encoding was found.</p>
+ </desc>
+ </func>
+ <func>
<name name="format_error" arity="1"/>
<fsummary>Format an error descriptor</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml
index 57b5828bcd..9ae4f3d91f 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>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -63,6 +63,12 @@
breaks and only a space is used as a separator.</p>
</desc>
</datatype>
+ <datatype>
+ <name name="option"/>
+ </datatype>
+ <datatype>
+ <name name="options"/>
+ </datatype>
</datatypes>
<funcs>
<func>
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index e6d262466c..22cd45a482 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -28,9 +28,9 @@
<rev></rev>
</header>
<module>io</module>
- <modulesummary>Standard IO Server Interface Functions</modulesummary>
+ <modulesummary>Standard I/O Server Interface Functions</modulesummary>
<description>
- <p>This module provides an interface to standard Erlang IO servers.
+ <p>This module provides an interface to standard Erlang I/O servers.
The output functions all return <c>ok</c> if they are successful,
or exit if they are not.</p>
<p>In the following description, all functions have an optional
@@ -38,17 +38,16 @@
process which handles the IO protocols. Normally, it is the
<c>IoDevice</c> returned by
<seealso marker="kernel:file#open/2">file:open/2</seealso>.</p>
- <p>For a description of the IO protocols refer to the STDLIB Users Guide.</p>
+ <p>For a description of the IO protocols refer to the <seealso marker="io_protocol">STDLIB User's Guide</seealso>.</p>
<warning>
<p>As of R13A, data supplied to the <seealso
marker="#put_chars/2">put_chars</seealso> function should be in the
<seealso marker="unicode#type-chardata"><c>unicode:chardata()</c></seealso> format. This means that programs
supplying binaries to this function need to convert them to UTF-8
- before trying to output the data on an
- <c>io_device()</c>.</p>
+ before trying to output the data on an IO device.</p>
- <p>If an io_device() is set in binary mode, the functions <seealso
+ <p>If an IO device is set in binary mode, the functions <seealso
marker="#get_chars/3">get_chars</seealso> and <seealso
marker="#get_line/2">get_line</seealso> may return binaries
instead of lists. The binaries will, as of R13A, be encoded in
@@ -68,9 +67,9 @@
<datatype>
<name name="device"/>
<desc>
- <p>Either <c>standard_io</c>, <c>standard_error</c>, a
+ <p>An IO device. Either <c>standard_io</c>, <c>standard_error</c>, a
registered name, or a pid handling IO protocols (returned from
- <seealso marker="kernel:file#open/2">file:open/2</seealso>).</p>
+ <seealso marker="kernel:file#open/2">file:open/2</seealso>).</p>
</desc>
</datatype>
<datatype>
@@ -89,17 +88,14 @@
<name name="format"/>
</datatype>
<datatype>
- <name name="line"/>
+ <name name="location"/>
</datatype>
<datatype>
<name name="prompt"/>
</datatype>
<datatype>
- <name name="request_error"/>
- </datatype>
- <datatype>
- <name name="error_description"/>
- <desc><p>Whatever the I/O-server sends.</p></desc>
+ <name name="server_no_data"/>
+ <desc><p>What the I/O-server sends when there is no data.</p></desc>
</datatype>
</datatypes>
@@ -107,11 +103,11 @@
<func>
<name name="columns" arity="0"/>
<name name="columns" arity="1"/>
- <fsummary>Get the number of columns of a device</fsummary>
+ <fsummary>Get the number of columns of an IO device</fsummary>
<desc>
<p>Retrieves the number of columns of the
<c><anno>IoDevice</anno></c> (i.e. the width of a terminal). The function
- only succeeds for terminal devices, for all other devices
+ only succeeds for terminal devices, for all other IO devices
the function returns <c>{error, enotsup}</c></p>
</desc>
</func>
@@ -120,7 +116,7 @@
<name name="put_chars" arity="2"/>
<fsummary>Write a list of characters</fsummary>
<desc>
- <p>Writes the characters of <c><anno>CharData</anno></c> to the io_server()
+ <p>Writes the characters of <c><anno>CharData</anno></c> to the I/O server
(<c><anno>IoDevice</anno></c>).</p>
</desc>
</func>
@@ -135,6 +131,7 @@
<func>
<name name="get_chars" arity="2"/>
<name name="get_chars" arity="3"/>
+ <type name="server_no_data"/>
<fsummary>Read a specified number of characters</fsummary>
<desc>
<p>Reads <c><anno>Count</anno></c> characters from standard input
@@ -143,19 +140,19 @@
<taglist>
<tag><c><anno>Data</anno></c></tag>
<item>
- <p>The input characters. If the device supports Unicode,
+ <p>The input characters. If the IO device supports Unicode,
the data may represent codepoints larger than 255 (the
- latin1 range). If the io_server() is set to deliver
+ latin1 range). If the I/O server is set to deliver
binaries, they will be encoded in UTF-8 (regardless of if
- the device actually supports Unicode or not).</p>
+ the IO device actually supports Unicode or not).</p>
</item>
<tag><c>eof</c></tag>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error,<anno>Reason</anno>}</c></tag>
+ <tag><c>{error, <anno>ErrorDescription</anno>}</c></tag>
<item>
- <p>Other (rare) error condition, for instance <c>{error,estale}</c>
+ <p>Other (rare) error condition, for instance <c>{error, estale}</c>
if reading from an NFS file system.</p>
</item>
</taglist>
@@ -164,6 +161,7 @@
<func>
<name name="get_line" arity="1"/>
<name name="get_line" arity="2"/>
+ <type name="server_no_data"/>
<fsummary>Read a line</fsummary>
<desc>
<p>Reads a line from the standard input (<c><anno>IoDevice</anno></c>),
@@ -172,19 +170,19 @@
<tag><c><anno>Data</anno></c></tag>
<item>
<p>The characters in the line terminated by a LF (or end of
- file). If the device supports Unicode,
+ file). If the IO device supports Unicode,
the data may represent codepoints larger than 255 (the
- latin1 range). If the io_server() is set to deliver
+ latin1 range). If the I/O server is set to deliver
binaries, they will be encoded in UTF-8 (regardless of if
- the device actually supports Unicode or not).</p>
+ the IO device actually supports Unicode or not).</p>
</item>
<tag><c>eof</c></tag>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error,<anno>Reason</anno>}</c></tag>
+ <tag><c>{error, <anno>ErrorDescription</anno>}</c></tag>
<item>
- <p>Other (rare) error condition, for instance <c>{error,estale}</c>
+ <p>Other (rare) error condition, for instance <c>{error, estale}</c>
if reading from an NFS file system.</p>
</item>
</taglist>
@@ -195,7 +193,7 @@
<name name="getopts" arity="1"/>
<fsummary>Get the supported options and values from an I/O-server</fsummary>
<desc>
- <p>This function requests all available options and their current values for a specific io_device(). Example:</p>
+ <p>This function requests all available options and their current values for a specific IO device. Example:</p>
<pre>
1> <input>{ok,F} = file:open("/dev/null",[read]).</input>
{ok,&lt;0.42.0&gt;}
@@ -217,30 +215,30 @@
<name name="setopts" arity="2"/>
<fsummary>Set options</fsummary>
<desc>
- <p>Set options for the io_device() (<c><anno>IoDevice</anno></c>).</p>
+ <p>Set options for the standard IO device (<c><anno>IoDevice</anno></c>).</p>
<p>Possible options and values vary depending on the actual
- io_device(). For a list of supported options and their current values
- on a specific device, use the <seealso
+ IO device. For a list of supported options and their current values
+ on a specific IO device, use the <seealso
marker="#getopts/1">getopts/1</seealso> function.</p>
- <p>The options and values supported by the current OTP io_devices are:</p>
+ <p>The options and values supported by the current OTP IO devices are:</p>
<taglist>
<tag><c>binary, list or {binary, boolean()}</c></tag>
<item>
- <p>If set in binary mode (binary or {binary,true}), the io_server() sends binary data (encoded in UTF-8) as answers to the get_line, get_chars and, if possible, get_until requests (see the I/O protocol description in STDLIB User's Guide for details). The immediate effect is that <c>get_chars/2,3</c> and <c>get_line/1,2</c> return UTF-8 binaries instead of lists of chars for the affected device.</p>
- <p>By default, all io_devices in OTP are set in list mode, but the io functions can handle any of these modes and so should other, user written, modules behaving as clients to I/O-servers.</p>
- <p>This option is supported by the standard shell (group.erl), the 'oldshell' (user.erl) and the file I/O servers.</p>
+ <p>If set in binary mode (<c>binary</c> or <c>{binary, true}</c>), the I/O server sends binary data (encoded in UTF-8) as answers to the <c>get_line</c>, <c>get_chars</c> and, if possible, <c>get_until</c> requests (see the I/O protocol description in <seealso marker="io_protocol">STDLIB User's Guide</seealso> for details). The immediate effect is that <c>get_chars/2,3</c> and <c>get_line/1,2</c> return UTF-8 binaries instead of lists of chars for the affected IO device.</p>
+ <p>By default, all IO devices in OTP are set in list mode, but the I/O functions can handle any of these modes and so should other, user written, modules behaving as clients to I/O-servers.</p>
+ <p>This option is supported by the standard shell (<c>group.erl</c>), the 'oldshell' (<c>user.erl</c>) and the file I/O servers.</p>
</item>
<tag><c>{echo, boolean()}</c></tag>
<item>
- <p>Denotes if the terminal should echo input. Only supported for the standard shell I/O-server (group.erl)</p>
+ <p>Denotes if the terminal should echo input. Only supported for the standard shell I/O-server (<c>group.erl</c>)</p>
</item>
<tag><c>{expand_fun, expand_fun()}</c></tag>
<item>
<p>Provide a function for tab-completion (expansion)
- like the erlang shell. This function is called
- when the user presses the Tab key. The expansion is
+ like the Erlang shell. This function is called
+ when the user presses the TAB key. The expansion is
active when calling line-reading functions such as
<c>get_line/1,2</c>.</p>
<p>The function is called with the current line, upto
@@ -253,25 +251,25 @@
will be printed and the current input line will be written
once again.</p>
<p>Trivial example (beep on anything except empty line, which
- is expanded to "quit"):</p>
+ is expanded to <c>"quit"</c>):</p>
<code type="none">
fun("") -> {yes, "quit", []};
(_) -> {no, "", ["quit"]} end</code>
- <p>This option is supported by the standard shell only (group.erl).</p>
+ <p>This option is supported by the standard shell only (<c>group.erl</c>).</p>
</item>
<tag><c>{encoding, latin1 | unicode}</c></tag>
<item>
- <p>Specifies how characters are input or output from or to the actual device, implying that i.e. a terminal is set to handle Unicode input and output or a file is set to handle UTF-8 data encoding.</p>
- <p>The option <em>does not</em> affect how data is returned from the io-functions or how it is sent in the I/O-protocol, it only affects how the io_device() is to handle Unicode characters towards the &quot;physical&quot; device.</p>
- <p>The standard shell will be set for either unicode or latin1 encoding when the system is started. The actual encoding is set with the help of the "LANG" or "LC_CTYPE" environment variables on Unix-like system or by other means on other systems. The bottom line is that the user can input Unicode characters and the device will be in {encoding, unicode} mode if the device supports it. The mode can be changed, if the assumption of the runtime system is wrong, by setting this option.</p>
- <p>The io_device() used when Erlang is started with the "-oldshell" or "-noshell" flags is by default set to latin1 encoding, meaning that any characters beyond codepoint 255 will be escaped and that input is expected to be plain 8-bit ISO-latin-1. If the encoding is changed to Unicode, input and output from the standard file descriptors will be in UTF-8 (regardless of operating system).</p>
- <p>Files can also be set in {encoding, unicode}, meaning that data is written and read as UTF-8. More encodings are possible for files, see below.</p>
- <p>{encoding, unicode | latin1} is supported by both the standard shell (group.erl including werl on windows), the 'oldshell' (user.erl) and the file I/O servers.</p>
+ <p>Specifies how characters are input or output from or to the actual IO device, implying that i.e. a terminal is set to handle Unicode input and output or a file is set to handle UTF-8 data encoding.</p>
+ <p>The option <em>does not</em> affect how data is returned from the I/O functions or how it is sent in the I/O-protocol, it only affects how the IO device is to handle Unicode characters towards the &quot;physical&quot; device.</p>
+ <p>The standard shell will be set for either Unicode or latin1 encoding when the system is started. The actual encoding is set with the help of the <c>LANG</c> or <c>LC_CTYPE</c> environment variables on Unix-like system or by other means on other systems. The bottom line is that the user can input Unicode characters and the IO device will be in <c>{encoding, unicode}</c> mode if the IO device supports it. The mode can be changed, if the assumption of the runtime system is wrong, by setting this option.</p>
+ <p>The IO device used when Erlang is started with the "-oldshell" or "-noshell" flags is by default set to latin1 encoding, meaning that any characters beyond codepoint 255 will be escaped and that input is expected to be plain 8-bit ISO-latin-1. If the encoding is changed to Unicode, input and output from the standard file descriptors will be in UTF-8 (regardless of operating system).</p>
+ <p>Files can also be set in <c>{encoding, unicode}</c>, meaning that data is written and read as UTF-8. More encodings are possible for files, see below.</p>
+ <p><c>{encoding, unicode | latin1}</c> is supported by both the standard shell (<c>group.erl</c> including <c>werl</c> on Windows&reg;), the 'oldshell' (<c>user.erl</c>) and the file I/O servers.</p>
</item>
<tag><c>{encoding, utf8 | utf16 | utf32 | {utf16,big} | {utf16,little} | {utf32,big} | {utf32,little}}</c></tag>
<item>
<p>For disk files, the encoding can be set to various UTF variants. This will have the effect that data is expected to be read as the specified encoding from the file and the data will be written in the specified encoding to the disk file.</p>
- <p>{encoding, utf8} will have the same effect as {encoding,unicode} on files.</p>
+ <p><c>{encoding, utf8}</c> will have the same effect as <c>{encoding, unicode}</c> on files.</p>
<p>The extended encodings are only supported on disk files (opened by the <seealso marker="kernel:file#open/2">file:open/2</seealso> function)</p>
</item>
</taglist>
@@ -289,6 +287,7 @@
<func>
<name name="read" arity="1"/>
<name name="read" arity="2"/>
+ <type name="server_no_data"/>
<fsummary>Read a term</fsummary>
<desc>
<p>Reads a term <c><anno>Term</anno></c> from the standard input
@@ -312,21 +311,25 @@
</func>
<func>
<name name="read" arity="3"/>
+ <name name="read" arity="4"/>
+ <type name="server_no_data"/>
<fsummary>Read a term</fsummary>
<desc>
<p>Reads a term <c><anno>Term</anno></c> from <c><anno>IoDevice</anno></c>, prompting it
- with <c><anno>Prompt</anno></c>. Reading starts at line number
- <c><anno>StartLine</anno></c>. It returns:</p>
+ with <c><anno>Prompt</anno></c>. Reading starts at location
+ <c><anno>StartLocation</anno></c>. The argument
+ <c><anno>Options</anno></c> is passed on as the <c>Options</c>
+ argument of the <c>erl_scan:tokens/4</c> function. It returns:</p>
<taglist>
- <tag><c>{ok, Term, <anno>EndLine</anno>}</c></tag>
+ <tag><c>{ok, Term, <anno>EndLocation</anno>}</c></tag>
<item>
<p>The parsing was successful.</p>
</item>
- <tag><c>{eof, <anno>EndLine</anno>}</c></tag>
+ <tag><c>{eof, <anno>EndLocation</anno>}</c></tag>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, <anno>ErrorInfo</anno>, <anno>ErrorLine</anno>}</c></tag>
+ <tag><c>{error, <anno>ErrorInfo</anno>, <anno>ErrorLocation</anno>}</c></tag>
<item>
<p>The parsing failed.</p>
</item>
@@ -377,7 +380,7 @@ ok</pre>
applicable, it is used for both the field width and precision.
The default padding character is <c>' '</c> (space).</p>
<p><c>Mod</c> is the control sequence modifier. It is either a
- single character (currently only 't', for unicode translation,
+ single character (currently only <c>t</c>, for Unicode translation,
is supported) that changes the interpretation of Data.</p>
<p>The following control sequences are available:</p>
@@ -397,9 +400,9 @@ ok</pre>
2> <input>io:fwrite("|~10.5c|~-10.5c|~5c|~n", [$a, $b, $c]).</input>
| aaaaa|bbbbb |ccccc|
ok</pre>
- <p>If the Unicode translation modifier ('t') is in effect,
+ <p>If the Unicode translation modifier (<c>t</c>) is in effect,
the integer argument can be any number representing a
- valid unicode codepoint, otherwise it should be an integer
+ valid Unicode codepoint, otherwise it should be an integer
less than or equal to 255, otherwise it is masked with 16#FF:</p>
<pre>
1> <input>io:fwrite("~tc~n",[1024]).</input>
@@ -439,7 +442,7 @@ ok</pre>
<item>
<p>Prints the argument with the <c>string</c> syntax. The
argument is, if no Unicode translation modifier is present, an
- iolist(), a binary, or an atom. If the Unicode translation modifier ('t') is in effect, the argument is unicode:chardata(), meaning that binaries are in UTF-8. The characters
+ iolist(), a binary, or an atom. If the Unicode translation modifier (<c>t</c>) is in effect, the argument is unicode:chardata(), meaning that binaries are in UTF-8. The characters
are printed without quotes. The string is first truncated
by the given precision and then padded and justified
to the given field width. The default precision is the field width.</p>
@@ -476,8 +479,10 @@ ok
<p>Writes the data with standard syntax in the same way as
<c>~w</c>, but breaks terms whose printed representation
is longer than one line into many lines and indents each
- line sensibly. It also tries to detect lists of printable
- characters and to output these as strings. For example:</p>
+ line sensibly. It also tries to detect lists of
+ printable characters and to output these as strings. The
+ Unicode translation modifier is used for determining
+ what characters are printable. For example:</p>
<pre>
5> <input>T = [{attributes,[[{id,age,1.50000},{mode,explicit},</input>
<input>{typename,"INTEGER"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},</input>
@@ -516,6 +521,19 @@ Here T = [{attributes,[[{id,age,1.5},
{tag,{'PRIVATE',3}},
{mode,implicit}]
ok</pre>
+ <p>Binaries that look like UTF-8 encoded strings will be
+ output with the string syntax if the Unicode translation
+ modifier is given:</p>
+ <pre>
+9> <input>io:fwrite("~p~n",[[1024]]).</input>
+[1024]
+10> <input>io:fwrite("~tp~n",[[1024]]).</input>
+"\x{400}"
+11> <input>io:fwrite("~tp~n", [&lt;&lt;128,128&gt;&gt;]).</input>
+&lt;&lt;128,128&gt;&gt;
+12> <input>io:fwrite("~tp~n", [&lt;&lt;208,128&gt;&gt;]).</input>
+&lt;&lt;"\x{400}"/utf8&gt;&gt;
+ok</pre>
</item>
<tag><c>W</c></tag>
<item>
@@ -583,7 +601,7 @@ ok</pre>
<tag><c>#</c></tag>
<item>
<p>Like <c>B</c>, but prints the number with an Erlang style
- '#'-separated base prefix.</p>
+ <c>#</c>-separated base prefix.</p>
<pre>
16> <input>io:fwrite("~.10#~n", [31]).</input>
10#31
@@ -633,13 +651,14 @@ ok
{shell,eval_loop,3}]}
in function io:o_request/2</pre>
<p>In this example, an attempt was made to output the single
- character '65' with the aid of the string formatting directive
+ character 65 with the aid of the string formatting directive
"~s".</p>
</desc>
</func>
<func>
<name name="fread" arity="2"/>
<name name="fread" arity="3"/>
+ <type name="server_no_data"/>
<fsummary>Read formatted input</fsummary>
<desc>
<p>Reads characters from the standard input (<c><anno>IoDevice</anno></c>),
@@ -664,7 +683,7 @@ ok
return suppression character. It provides a method to
specify a field which is to be omitted. <c>F</c> is the
<c>field width</c> of the input field, <c>M</c> is an optional
- translation modifier (of which 't' is the only currently
+ translation modifier (of which <c>t</c> is the only currently
supported, meaning Unicode translation) and <c>C</c>
determines the type of control sequence.</p>
@@ -690,8 +709,8 @@ ok
<tag><c>-</c></tag>
<item>
<p>An optional sign character is expected. A sign
- character '-' gives the return value <c>-1</c>. Sign
- character '+' or none gives <c>1</c>. The field width
+ character <c>-</c> gives the return value <c>-1</c>. Sign
+ character <c>+</c> or none gives <c>1</c>. The field width
parameter is ignored. Leading white-space characters
are not skipped.</p>
</item>
@@ -713,7 +732,7 @@ ok
characters are stripped. An Erlang string (list of
characters) is returned.</p>
- <p>If Unicode translation is in effect (~ts),
+ <p>If Unicode translation is in effect (<c>~ts</c>),
characters larger than 255 are accepted, otherwise
not. With the translation modifier, the list
returned may as a consequence also contain
@@ -769,10 +788,15 @@ Prompt> <input>&lt;Character beyond latin1 range not printable in this medium&gt
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, <anno>What</anno>}</c></tag>
+ <tag><c>{error, <anno>FreadError</anno>}</c></tag>
+ <item>
+ <p>The reading failed and <c>FreadError</c> gives a
+ hint about the error.</p>
+ </item>
+ <tag><c>{error, <anno>ErrorDescription</anno>}</c></tag>
<item>
<p>The read operation failed and the parameter
- <c><anno>What</anno></c> gives a hint about the error.</p>
+ <c><anno>ErrorDescription</anno></c> gives a hint about the error.</p>
</item>
</taglist>
</item>
@@ -793,11 +817,11 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
<func>
<name name="rows" arity="0"/>
<name name="rows" arity="1"/>
- <fsummary>Get the number of rows of a device</fsummary>
+ <fsummary>Get the number of rows of an IO device</fsummary>
<desc>
<p>Retrieves the number of rows of the
<c><anno>IoDevice</anno></c> (i.e. the height of a terminal). The function
- only succeeds for terminal devices, for all other devices
+ only succeeds for terminal devices, for all other IO devices
the function returns <c>{error, enotsup}</c></p>
</desc>
</func>
@@ -805,23 +829,28 @@ enter><input>:</input> <input>alan</input> <input>:</input> <input>joe</in
<name name="scan_erl_exprs" arity="1"/>
<name name="scan_erl_exprs" arity="2"/>
<name name="scan_erl_exprs" arity="3"/>
+ <name name="scan_erl_exprs" arity="4"/>
+ <type name="server_no_data"/>
<fsummary>Read and tokenize Erlang expressions</fsummary>
<desc>
<p>Reads data from the standard input (<c>IoDevice</c>),
- prompting it with <c>Prompt</c>. Reading starts at line number
- <c>StartLine</c> (1). The data is tokenized as if it were a
- sequence of Erlang expressions until a final <c>'.'</c> is
+ prompting it with <c>Prompt</c>. Reading starts at location
+ <c>StartLocation</c> (<c>1</c>). The argument <c><anno>Options</anno></c>
+ is passed on as the <c>Options</c> argument of the
+ <c>erl_scan:tokens/4</c> function. The data is tokenized as if
+ it were a
+ sequence of Erlang expressions until a final dot (<c>.</c>) is
reached. This token is also returned. It returns:</p>
<taglist>
- <tag><c>{ok, Tokens, EndLine}</c></tag>
+ <tag><c>{ok, Tokens, EndLocation}</c></tag>
<item>
<p>The tokenization succeeded.</p>
</item>
- <tag><c>{eof, EndLine}</c></tag>
+ <tag><c>{eof, EndLocation}</c></tag>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, ErrorInfo, ErrorLine}</c></tag>
+ <tag><c>{error, ErrorInfo, ErrorLocation}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -840,13 +869,18 @@ enter><input>1.0er.</input>
<name name="scan_erl_form" arity="1"/>
<name name="scan_erl_form" arity="2"/>
<name name="scan_erl_form" arity="3"/>
+ <name name="scan_erl_form" arity="4"/>
+ <type name="server_no_data"/>
<fsummary>Read and tokenize an Erlang form</fsummary>
<desc>
<p>Reads data from the standard input (<c><anno>IoDevice</anno></c>),
- prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number
- <c><anno>StartLine</anno></c> (1). The data is tokenized as if it were an
+ prompting it with <c><anno>Prompt</anno></c>. Starts reading
+ at location <c><anno>StartLocation</anno></c> (<c>1</c>). The
+ argument <c><anno>Options</anno></c> is passed on as the
+ <c>Options</c> argument of the <c>erl_scan:tokens/4</c>
+ function. The data is tokenized as if it were an
Erlang form - one of the valid Erlang expressions in an
- Erlang source file - until a final <c>'.'</c> is reached.
+ Erlang source file - until a final dot (<c>.</c>) is reached.
This last token is also returned. The return values are the
same as for <c>scan_erl_exprs/1,2,3</c> above.</p>
</desc>
@@ -855,24 +889,30 @@ enter><input>1.0er.</input>
<name name="parse_erl_exprs" arity="1"/>
<name name="parse_erl_exprs" arity="2"/>
<name name="parse_erl_exprs" arity="3"/>
+ <name name="parse_erl_exprs" arity="4"/>
<type name="parse_ret"/>
+ <type name="server_no_data"/>
<fsummary>Read, tokenize and parse Erlang expressions</fsummary>
<desc>
- <p>Reads data from the standard input (<c><anno>IoDevice</anno></c>),
- prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number
- <c><anno>StartLine</anno></c> (1). The data is tokenized and parsed as if
- it were a sequence of Erlang expressions until a final '.' is
- reached. It returns:</p>
+ <p>Reads data from the standard input
+ (<c><anno>IoDevice</anno></c>), prompting it with
+ <c><anno>Prompt</anno></c>. Starts reading at location
+ <c><anno>StartLocation</anno></c> (<c>1</c>). The argument
+ <c><anno>Options</anno></c> is passed on as the
+ <c>Options</c> argument of the <c>erl_scan:tokens/4</c>
+ function. The data is tokenized and parsed as if it were a
+ sequence of Erlang expressions until a final dot (<c>.</c>) is reached.
+ It returns:</p>
<taglist>
- <tag><c>{ok, ExprList, EndLine}</c></tag>
+ <tag><c>{ok, ExprList, EndLocation}</c></tag>
<item>
<p>The parsing was successful.</p>
</item>
- <tag><c>{eof, EndLine}</c></tag>
+ <tag><c>{eof, EndLocation}</c></tag>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, ErrorInfo, ErrorLine}</c></tag>
+ <tag><c>{error, ErrorInfo, ErrorLocation}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -891,25 +931,30 @@ enter><input>abc("hey".</input>
<name name="parse_erl_form" arity="1"/>
<name name="parse_erl_form" arity="2"/>
<name name="parse_erl_form" arity="3"/>
+ <name name="parse_erl_form" arity="4"/>
<type name="parse_form_ret"/>
+ <type name="server_no_data"/>
<fsummary>Read, tokenize and parse an Erlang form</fsummary>
<desc>
<p>Reads data from the standard input (<c><anno>IoDevice</anno></c>),
- prompting it with <c><anno>Prompt</anno></c>. Starts reading at line number
- <c><anno>StartLine</anno></c> (1). The data is tokenized and parsed as if
+ prompting it with <c><anno>Prompt</anno></c>. Starts reading at
+ location <c><anno>StartLocation</anno></c> (<c>1</c>). The argument
+ <c><anno>Options</anno></c> is passed on as the
+ <c>Options</c> argument of the <c>erl_scan:tokens/4</c>
+ function. The data is tokenized and parsed as if
it were an Erlang form - one of the valid Erlang expressions
- in an Erlang source file - until a final '.' is reached. It
+ in an Erlang source file - until a final dot (<c>.</c>) is reached. It
returns:</p>
<taglist>
- <tag><c>{ok, AbsForm, EndLine}</c></tag>
+ <tag><c>{ok, AbsForm, EndLocation}</c></tag>
<item>
<p>The parsing was successful.</p>
</item>
- <tag><c>{eof, EndLine}</c></tag>
+ <tag><c>{eof, EndLocation}</c></tag>
<item>
<p>End of file was encountered.</p>
</item>
- <tag><c>{error, ErrorInfo, ErrorLine}</c></tag>
+ <tag><c>{error, ErrorInfo, ErrorLocation}</c></tag>
<item>
<p>An error occurred.</p>
</item>
@@ -940,7 +985,7 @@ enter><input>bar.</input>
</section>
<section>
<title>Standard Error</title>
- <p>In certain situations, especially when the standard output is redirected, access to an io_server() specific for error messages might be convenient. The io_device 'standard_error' can be used to direct output to whatever the current operating system considers a suitable device for error output. Example on a Unix-like operating system:</p>
+ <p>In certain situations, especially when the standard output is redirected, access to an I/O-server specific for error messages might be convenient. The IO device <c>standard_error</c> can be used to direct output to whatever the current operating system considers a suitable IO device for error output. Example on a Unix-like operating system:</p>
<pre>
$ <input>erl -noshell -noinput -eval 'io:format(standard_error,"Error: ~s~n",["error 11"]),'\</input>
<input>'init:stop().' > /dev/null</input>
@@ -956,7 +1001,7 @@ Error: error 11</pre>
<c>ErrorInfo</c> structure which is returned from all IO modules.
It has the format:</p>
<code type="none">
-{ErrorLine, Module, ErrorDescriptor}</code>
+{ErrorLocation, Module, ErrorDescriptor}</code>
<p>A string which describes the error is obtained with the following
call:</p>
<code type="none">
diff --git a/lib/stdlib/doc/src/io_lib.xml b/lib/stdlib/doc/src/io_lib.xml
index 506c1792f1..617a6b74fc 100644
--- a/lib/stdlib/doc/src/io_lib.xml
+++ b/lib/stdlib/doc/src/io_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2011</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,6 +43,12 @@
<name name="chars"/>
</datatype>
<datatype>
+ <name name="unicode_chars"/>
+ </datatype>
+ <datatype>
+ <name name="unicode_string"/>
+ </datatype>
+ <datatype>
<name name="continuation"/>
<desc><p>A continuation as returned by <seealso marker="#fread/3"><c>fread/3</c></seealso>.</p>
</desc>
@@ -50,6 +56,9 @@
<datatype>
<name name="depth"/>
</datatype>
+ <datatype>
+ <name name="fread_error"/>
+ </datatype>
</datatypes>
<funcs>
<func>
@@ -209,6 +218,23 @@
</desc>
</func>
<func>
+ <name name="write_unicode_string" arity="1"/>
+ <fsummary>Write a Unicode string</fsummary>
+ <desc>
+ <p>Returns the list of characters needed to print
+ <c><anno>UnicodeString</anno></c> as a string.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="write_unicode_string_as_latin1" arity="1"/>
+ <fsummary>Write a Unicode string</fsummary>
+ <desc>
+ <p>Returns the list of characters needed to print
+ <c><anno>UnicodeString</anno></c> as a string. Non-Latin-1
+ characters are escaped.</p>
+ </desc>
+ </func>
+ <func>
<name name="write_char" arity="1"/>
<fsummary>Write a character</fsummary>
<desc>
@@ -217,6 +243,23 @@
</desc>
</func>
<func>
+ <name name="write_unicode_char" arity="1"/>
+ <fsummary>Write a Unicode character</fsummary>
+ <desc>
+ <p>Returns the list of characters needed to print a character
+ constant in the Unicode character set.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="write_unicode_char_as_latin1" arity="1"/>
+ <fsummary>Write a Unicode character</fsummary>
+ <desc>
+ <p>Returns the list of characters needed to print a character
+ constant in the Unicode character set. Non-Latin-1 characters
+ are escaped.</p>
+ </desc>
+ </func>
+ <func>
<name name="indentation" arity="2"/>
<fsummary>Indentation after printing string</fsummary>
<desc>
@@ -233,6 +276,14 @@
</desc>
</func>
<func>
+ <name name="unicode_char_list" arity="1"/>
+ <fsummary>Test for a list of Unicode characters</fsummary>
+ <desc>
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
+ characters in the Unicode range, otherwise it returns <c>false</c>.</p>
+ </desc>
+ </func>
+ <func>
<name name="deep_char_list" arity="1"/>
<fsummary>Test for a deep list of characters</fsummary>
<desc>
@@ -241,6 +292,14 @@
</desc>
</func>
<func>
+ <name name="deep_unicode_char_list" arity="1"/>
+ <fsummary>Test for a deep list of Unicode characters</fsummary>
+ <desc>
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a, possibly deep, list
+ of characters in the Unicode range, otherwise it returns <c>false</c>.</p>
+ </desc>
+ </func>
+ <func>
<name name="printable_list" arity="1"/>
<fsummary>Test for a list of printable ISO-latin-1 characters</fsummary>
<desc>
@@ -248,6 +307,14 @@
printable ISO-latin-1 characters, otherwise it returns <c>false</c>.</p>
</desc>
</func>
+ <func>
+ <name name="printable_unicode_list" arity="1"/>
+ <fsummary>Test for a list of printable Unicode characters</fsummary>
+ <desc>
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
+ printable Unicode characters, otherwise it returns <c>false</c>.</p>
+ </desc>
+ </func>
</funcs>
</erlref>
diff --git a/lib/stdlib/doc/src/io_protocol.xml b/lib/stdlib/doc/src/io_protocol.xml
index 0ff3d5c1ee..d36bf2042f 100644
--- a/lib/stdlib/doc/src/io_protocol.xml
+++ b/lib/stdlib/doc/src/io_protocol.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1999</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,10 +35,10 @@
<p>The I/O-protocol in Erlang specifies a way for a client to communicate
-with an io_server and vice versa. The io_server is a process handling the
-requests and that performs the requested task on i.e. a device. The
+with an I/O server and vice versa. The I/O server is a process that handles
+the requests and performs the requested task on e.g. an IO device. The
client is any Erlang process wishing to read or write data from/to the
-device.</p>
+IO device.</p>
<p>The common I/O-protocol has been present in OTP since the
beginning, but has been fairly undocumented and has also somewhat
@@ -53,85 +53,85 @@ implement than the original. It can certainly be argumented that the
current protocol is too complex, but this text describes how it looks
today, not how it should have looked.</p>
-<p>The basic ideas from the original protocol still hold. The io_server
+<p>The basic ideas from the original protocol still hold. The I/O server
and client communicate with one single, rather simplistic protocol and
-no server state is ever present in the client. Any io_server can be
+no server state is ever present in the client. Any I/O server can be
used together with any client code and client code need not be aware
-of the actual device the io_server communicates with.</p>
+of the actual IO device the I/O server communicates with.</p>
<section>
-<title>Protocol basics</title>
+<title>Protocol Basics</title>
-<p>As described in Robert's paper, servers and clients communicate using
-io_request/io_reply tuples as follows:</p>
+<p>As described in Robert's paper, I/O servers and clients communicate using
+<c>io_request</c>/<c>io_reply</c> tuples as follows:</p>
<p><em>{io_request, From, ReplyAs, Request}</em><br/>
<em>{io_reply, ReplyAs, Reply}</em></p>
-<p>The client sends an io_request to the io_server and the server
-eventually sends a corresponding reply.</p>
+<p>The client sends an <c>io_request</c> tuple to the I/O server and
+the server eventually sends a corresponding <c>io_reply</c> tuple.</p>
<list type="bulleted">
-<item>From is the pid() of the client, the process which the io_server
-sends the reply to.</item>
-
-<item>ReplyAs can be any datum and is simply returned in the corresponding
-io_reply. The io-module in the Erlang standard library simply uses the pid()
-of the io_server as the ReplyAs datum, but a more complicated client
-could have several outstanding io-requests to the same server and
-would then use i.e. a reference() or something else to differentiate among
-the incoming io_reply's. The ReplyAs element should be considered
-opaque by the io_server. Note that the pid() of the server is not
-explicitly present in the io_reply. The reply can be sent from any
-process, not necessarily the actual io_server. The ReplyAs element is
-the only thing that connects one io_request with an io_reply.</item>
-
-<item>Request and Reply are described below.</item>
+<item><c>From</c> is the <c>pid()</c> of the client, the process which
+the I/O server sends the IO reply to.</item>
+
+<item><c>ReplyAs</c> can be any datum and is returned in the corresponding
+<c>io_reply</c>. The <seealso marker="stdlib:io">io</seealso> module simply uses the pid()
+of the I/O server as the <c>ReplyAs</c> datum, but a more complicated client
+could have several outstanding I/O requests to the same I/O server and
+would then use i.e. a <c>reference()</c> or something else to differentiate among
+the incoming IO replies. The <c>ReplyAs</c> element should be considered
+opaque by the I/O server. Note that the <c>pid()</c> of the I/O server is not
+explicitly present in the <c>io_reply</c> tuple. The reply can be sent from any
+process, not necessarily the actual I/O server. The <c>ReplyAs</c> element is
+the only thing that connects one I/O request with an I/O-reply.</item>
+
+<item><c>Request</c> and <c>Reply</c> are described below.</item>
</list>
-<p>When an io_server receives an io_request, it acts upon the actual
-Request part and eventually sends an io_reply with the corresponding
-Reply part.</p>
+<p>When an I/O server receives an <c>io_request</c> tuple, it acts upon the actual
+<c>Request</c> part and eventually sends an <c>io_reply</c> tuple with the corresponding
+<c>Reply</c> part.</p>
</section>
<section>
-<title>Output requests</title>
+<title>Output Requests</title>
-<p>To output characters on a device, the following Requests exist:</p>
+<p>To output characters on an IO device, the following <c>Request</c>s exist:</p>
<p>
<em>{put_chars, Encoding, Characters}</em><br/>
<em>{put_chars, Encoding, Module, Function, Args}</em>
</p>
<list type="bulleted">
-<item>Encoding is either 'unicode' or 'latin1', meaning that the
+<item><c>Encoding</c> is either <c>unicode</c> or <c>latin1</c>, meaning that the
characters are (in case of binaries) encoded as either UTF-8 or
- iso-latin-1 (pure bytes). A well behaved io_server should also
- return error if list elements contain integers > 255 when the
- Encoding is set to latin1. Note that this does not in any way tell
- how characters should be put on the actual device or how the
- io_server should handle them. Different io_servers may handle the
- characters however they want, this simply tells the io_server which
- format the data is expected to have. In the Module/Function/argument
- case, the Encoding tells which format the designated function
- produces. Note that byte-oriented data is simplest sent using latin1
- Encoding</item>
-
-<item>Characters are the data to be put on the device. If Encoding is
- latin1, this is an iolist(). If Encoding is unicode, this is an
- Erlang standard mixed unicode list (one integer in a list per
+ ISO-latin-1 (pure bytes). A well behaved I/O server should also
+ return error if list elements contain integers > 255 when
+ <c>Encoding</c> is set to <c>latin1</c>. Note that this does not in any way tell
+ how characters should be put on the actual IO device or how the
+ I/O server should handle them. Different I/O servers may handle the
+ characters however they want, this simply tells the I/O server which
+ format the data is expected to have. In the <c>Module</c>/<c>Function</c>/<c>Args</c>
+ case, <c>Encoding</c> tells which format the designated function
+ produces. Note that byte-oriented data is simplest sent using the ISO-latin-1
+ encoding.</item>
+
+<item>Characters are the data to be put on the IO device. If <c>Encoding</c> is
+ <c>latin1</c>, this is an <c>iolist()</c>. If <c>Encoding</c> is <c>unicode</c>, this is an
+ Erlang standard mixed Unicode list (one integer in a list per
character, characters in binaries represented as UTF-8).</item>
-<item>Module, Function, Args denotes a function which will be called to
- produce the data (like io_lib:format). Args is a list of arguments
+<item><c>Module</c>, <c>Function</c>, and <c>Args</c> denote a function which will be called to
+ produce the data (like <c>io_lib:format/2</c>). <c>Args</c> is a list of arguments
to the function. The function should produce data in the given
- Encoding. The io_server should call the function as apply(Mod, Func,
- Args) and will put the returned data on the device as if it was sent
- in a {put_chars, Encoding, Characters} request. If the function
+ <c>Encoding</c>. The I/O server should call the function as
+ <c>apply(Mod, Func, Args)</c> and will put the returned data on the IO device as if it was sent
+ in a <c>{put_chars, Encoding, Characters}</c> request. If the function
returns anything else than a binary or list or throws an exception,
an error should be sent back to the client.</item>
</list>
-<p>The server replies to the client with an io_reply where the Reply
+<p>The I/O server replies to the client with an <c>io_reply</c> tuple where the <c>Reply</c>
element is one of:</p>
<p>
<em>ok</em><br/>
@@ -139,49 +139,50 @@ element is one of:</p>
</p>
<list type="bulleted">
-<item>Error describes the error to the client, which may do whatever it
- wants with it. The Erlang io-module typically returns it as is.</item>
+<item><c>Error</c> describes the error to the client, which may do whatever
+ it wants with it. The Erlang <seealso marker="stdlib:io">io</seealso>
+ module typically returns it as is.</item>
</list>
-<p>For backward compatibility the following Requests should also be
-handled by an io_server (these messages should not be present after
+<p>For backward compatibility the following <c>Request</c>s should also be
+handled by an I/O server (these requests should not be present after
R15B of OTP):</p>
<p>
<em>{put_chars, Characters}</em><br/>
<em>{put_chars, Module, Function, Args}</em>
</p>
-<p>These should behave as {put_chars, latin1, Characters} and {put_chars,
-latin1, Module, Function, Args} respectively. </p>
+<p>These should behave as <c>{put_chars, latin1, Characters}</c> and
+<c>{put_chars, latin1, Module, Function, Args}</c> respectively. </p>
</section>
<section>
<title>Input Requests</title>
-<p>To read characters from a device, the following Requests exist:</p>
+<p>To read characters from an IO device, the following <c>Request</c>s exist:</p>
<p><em>{get_until, Encoding, Prompt, Module, Function, ExtraArgs}</em></p>
<list type="bulleted">
-<item>Encoding denotes how data is to be sent back to the client and
+<item><c>Encoding</c> denotes how data is to be sent back to the client and
what data is sent to the function denoted by
- Module/Function/ExtraArgs. If the function supplied returns data as a
+ <c>Module</c>/<c>Function</c>/<c>ExtraArgs</c>. If the function supplied returns data as a
list, the data is converted to this encoding. If however the
function supplied returns data in some other format, no conversion
- can be done and it's up to the client supplied function to return
- data in a proper way. If Encoding is latin1, lists of integers
+ can be done and it is up to the client supplied function to return
+ data in a proper way. If <c>Encoding</c> is <c>latin1</c>, lists of integers
0..255 or binaries containing plain bytes are sent back to the
- client when possible, if Encoding is unicode, lists with integers in
- the whole unicode range or binaries encoded in UTF-8 are sent to the
+ client when possible; if <c>Encoding</c> is <c>unicode</c>, lists with integers in
+ the whole Unicode range or binaries encoded in UTF-8 are sent to the
client. The user supplied function will always see lists of integers, never
- binaries, but the list may contain numbers > 255 if the Encoding is
- 'unicode'.</item>
+ binaries, but the list may contain numbers > 255 if the <c>Encoding</c> is
+ <c>unicode</c>.</item>
-<item>Prompt is a list of characters (not mixed, no binaries) or an atom()
- to be output as a prompt for input on the device. The Prompt is
- often ignored by the io_server and a Prompt set to '' should always
- be ignored (and result in nothing being written to the device).</item>
+<item><c>Prompt</c> is a list of characters (not mixed, no binaries) or an atom
+ to be output as a prompt for input on the IO device. <c>Prompt</c> is
+ often ignored by the I/O server and if set to <c>''</c> it should always
+ be ignored (and result in nothing being written to the IO device).</item>
-<item><p>Module, Function, ExtraArgs denotes a function and arguments to
+<item><p><c>Module</c>, <c>Function</c>, and <c>ExtraArgs</c> denote a function and arguments to
determine when enough data is written. The function should take two
additional arguments, the last state, and a list of characters. The
function should return one of:</p>
@@ -189,23 +190,23 @@ latin1, Module, Function, Args} respectively. </p>
<em>{done, Result, RestChars}</em><br/>
<em>{more, Continuation}</em>
</p>
- <p>The Result can be any Erlang term, but if it is a list(), the
- io_server may convert it to a binary() of appropriate format before
- returning it to the client, if the server is set in binary mode (see
+ <p>The <c>Result</c> can be any Erlang term, but if it is a <c>list()</c>, the
+ I/O server may convert it to a <c>binary()</c> of appropriate format before
+ returning it to the client, if the I/O server is set in binary mode (see
below).</p>
- <p>The function will be called with the data the io_server finds on
- its device, returning {done, Result, RestChars} when enough data is
- read (in which case Result is sent to the client and RestChars are
- kept in the io_server as a buffer for subsequent input) or {more,
- Continuation}, indicating that more characters are needed to
- complete the request. The Continuation will be sent as the state in
+ <p>The function will be called with the data the I/O server finds on
+ its IO device, returning <c>{done, Result, RestChars}</c> when enough data is
+ read (in which case <c>Result</c> is sent to the client and <c>RestChars</c> is
+ kept in the I/O server as a buffer for subsequent input) or
+ <c>{more, Continuation}</c>, indicating that more characters are needed to
+ complete the request. The <c>Continuation</c> will be sent as the state in
subsequent calls to the function when more characters are
available. When no more characters are available, the function
- shall return {done,eof,Rest}.
+ shall return <c>{done, eof, Rest}</c>.
The initial state is the empty list and the data when an
- end of file is reached on the device is the atom 'eof'. An emulation
- of the get_line request could be (inefficiently) implemented using
+ end of file is reached on the IO device is the atom <c>eof</c>. An emulation
+ of the <c>get_line</c> request could be (inefficiently) implemented using
the following functions:</p>
<code>
-module(demo).
@@ -214,7 +215,9 @@ latin1, Module, Function, Args} respectively. </p>
until_newline(_ThisFar,eof,_MyStopCharacter) -&gt;
{done,eof,[]};
until_newline(ThisFar,CharList,MyStopCharacter) -&gt;
- case lists:splitwith(fun(X) -&gt; X =/= MyStopCharacter end, CharList) of
+ case
+ lists:splitwith(fun(X) -&gt; X =/= MyStopCharacter end, CharList)
+ of
{L,[]} -&gt;
{more,ThisFar++L};
{L2,[MyStopCharacter|Rest]} -&gt;
@@ -222,45 +225,47 @@ until_newline(ThisFar,CharList,MyStopCharacter) -&gt;
end.
get_line(IoServer) -&gt;
- IoServer ! {io_request, self(), IoServer, {get_until, unicode, '',
- ?MODULE, until_newline, [$\n]}},
+ IoServer ! {io_request,
+ self(),
+ IoServer,
+ {get_until, unicode, '', ?MODULE, until_newline, [$\n]}},
receive
{io_reply, IoServer, Data} -&gt;
Data
end.
</code>
- <p>Note especially that the last element in the Request tuple ([$\n])
+ <p>Note especially that the last element in the <c>Request</c> tuple (<c>[$\n]</c>)
is appended to the argument list when the function is called. The
function should be called like
- apply(Module, Function, [ State, Data | ExtraArgs ]) by the io_server</p>
+ <c>apply(Module, Function, [ State, Data | ExtraArgs ])</c> by the I/O server</p>
</item>
</list>
-<p>A defined number of characters is requested using this Request:</p>
+<p>A fixed number of characters is requested using this <c>Request</c>:</p>
<p>
<em>{get_chars, Encoding, Prompt, N}</em>
</p>
<list type="bulleted">
-<item>Encoding and Prompt as for get_until.</item>
+<item><c>Encoding</c> and <c>Prompt</c> as for <c>get_until</c>.</item>
-<item>N is the number of characters to be read from the device.</item>
+<item><c>N</c> is the number of characters to be read from the IO device.</item>
</list>
-<p>A single line (like in the example above) is requested with this Request:</p>
+<p>A single line (like in the example above) is requested with this <c>Request</c>:</p>
<p>
<em>{get_line, Encoding, Prompt}</em>
</p>
<list type="bulleted">
-<item>Encoding and prompt as above.</item>
+<item><c>Encoding</c> and <c>Prompt</c> as above.</item>
</list>
-<p>Obviously, get_chars and get_line could be implemented with the
-get_until request (and indeed was originally), but demands for
+<p>Obviously, the <c>get_chars</c> and <c>get_line</c> could be implemented with the
+<c>get_until</c> request (and indeed they were originally), but demands for
efficiency has made these additions necessary.</p>
-<p>The server replies to the client with an io_reply where the Reply
+<p>The I/O server replies to the client with an <c>io_reply</c> tuple where the <c>Reply</c>
element is one of:</p>
<p>
<em>Data</em><br/>
@@ -269,16 +274,17 @@ element is one of:</p>
</p>
<list type="bulleted">
-<item>Data is the characters read, in either list or binary form
- (depending on the io_server mode, see below).</item>
-<item>Error describes the error to the client, which may do whatever it
- wants with it. The Erlang io-module typically returns it as is.</item>
-<item>eof is returned when input end is reached and no more data is
+<item><c>Data</c> is the characters read, in either list or binary form
+ (depending on the I/O server mode, see below).</item>
+<item><c>Error</c> describes the error to the client, which may do whatever it
+ wants with it. The Erlang <seealso marker="stdlib:io">io</seealso>
+ module typically returns it as is.</item>
+<item><c>eof</c> is returned when input end is reached and no more data is
available to the client process.</item>
</list>
-<p>For backward compatibility the following Requests should also be
-handled by an io_server (these messages should not be present after
+<p>For backward compatibility the following <c>Request</c>s should also be
+handled by an I/O server (these reqeusts should not be present after
R15B of OTP):</p>
<p>
@@ -287,30 +293,30 @@ R15B of OTP):</p>
<em>{get_line, Prompt}</em><br/>
</p>
-<p>These should behave as {get_until, latin1, Prompt, Module, Function,
-ExtraArgs}, {get_chars, latin1, Prompt, N} and {get_line, latin1,
-Prompt} respectively.</p>
+<p>These should behave as <c>{get_until, latin1, Prompt, Module, Function,
+ExtraArgs}</c>, <c>{get_chars, latin1, Prompt, N}</c> and <c>{get_line, latin1,
+Prompt}</c> respectively.</p>
</section>
<section>
-<title>I/O-server modes</title>
-
-<p>Demands for efficiency when reading data from an io_server has not
-only lead to the addition of the get_line and get_chars requests, but
-has also added the concept of io_server options. No options are
-mandatory to implement, but all io_servers in the Erlang standard
-libraries honor the 'binary' option, which allows the Data in the
-io_reply to be binary instead of in list form <em>when possible</em>.
+<title>I/O-server Modes</title>
+
+<p>Demands for efficiency when reading data from an I/O server has not
+only lead to the addition of the <c>get_line</c> and <c>get_chars</c> requests, but
+has also added the concept of I/O server options. No options are
+mandatory to implement, but all I/O servers in the Erlang standard
+libraries honor the <c>binary</c> option, which allows the <c>Data</c> element of the
+<c>io_reply</c> tuple to be a binary instead of a list <em>when possible</em>.
If the data is sent as a binary, Unicode data will be sent in the
-standard Erlang unicode
-format, i.e. UTF-8 (note that the function in get_until still gets
-list data regardless of the io_server mode).</p>
+standard Erlang Unicode
+format, i.e. UTF-8 (note that the function of the <c>get_until</c> request still gets
+list data regardless of the I/O server mode).</p>
-<p>Note that i.e. the <c>get_until</c> request allows for a function with the data specified as always being a list. Also the return value data from such a function can be of any type (as is indeed the case when an io:fread request is sent to an io_server). The client has to be prepared for data received as answers to those requests to be in a variety of forms, but the server should convert the results to binaries whenever possible (i.e. when the function supplied to get_until actually returns a list). The example shown later in this text does just that.</p>
+<p>Note that i.e. the <c>get_until</c> request allows for a function with the data specified as always being a list. Also the return value data from such a function can be of any type (as is indeed the case when an <c>io:fread</c> request is sent to an I/O server). The client has to be prepared for data received as answers to those requests to be in a variety of forms, but the I/O server should convert the results to binaries whenever possible (i.e. when the function supplied to <c>get_until</c> actually returns a list). The example shown later in this text does just that.</p>
<p>An I/O-server in binary mode will affect the data sent to the client,
so that it has to be able to handle binary data. For convenience, it
-is possible to set and retrieve the modes of an io_server using the
-following I/O-requests:</p>
+is possible to set and retrieve the modes of an I/O server using the
+following I/O requests:</p>
<p>
<em>{setopts, Opts}</em>
@@ -318,72 +324,72 @@ following I/O-requests:</p>
<list type="bulleted">
-<item>Opts is a list of options in the format recognized by proplists (and
- of course by the io_server itself).</item>
+<item><c>Opts</c> is a list of options in the format recognized by <seealso marker="stdlib:proplists">proplists</seealso> (and
+ of course by the I/O server itself).</item>
</list>
-<p>As an example, the io_server for the interactive shell (in group.erl)
+<p>As an example, the I/O server for the interactive shell (in <c>group.erl</c>)
understands the following options:</p>
<p>
-<em>{binary, bool()} (or 'binary'/'list')</em><br/>
-<em>{echo, bool()}</em><br/>
+<em>{binary, boolean()}</em> (or <em>binary</em>/<em>list</em>)<br/>
+<em>{echo, boolean()}</em><br/>
<em>{expand_fun, fun()}</em><br/>
-<em>{encoding, 'unicode'/'latin1'} (or 'unicode'/'latin1')</em>
+<em>{encoding, unicode/latin1}</em> (or <em>unicode</em>/<em>latin1</em>)
</p>
-<p>- of which the 'binary' and 'encoding' options are common for all
-io_servers in OTP, while 'echo' and 'expand' is valid only for this
-io_server. It's worth noting that the 'unicode' option notifies how
-characters are actually put on the physical device, i.e. if the
-terminal per se is unicode aware, it does not affect how characters
+<p>- of which the <c>binary</c> and <c>encoding</c> options are common for all
+I/O servers in OTP, while <c>echo</c> and <c>expand</c> are valid only for this
+I/O server. It is worth noting that the <c>unicode</c> option notifies how
+characters are actually put on the physical IO device, i.e. if the
+terminal per se is Unicode aware, it does not affect how characters
are sent in the I/O-protocol, where each request contains encoding
information for the provided or returned data.</p>
-<p>The server should send one of the following as Reply:</p>
+<p>The I/O server should send one of the following as <c>Reply</c>:</p>
<p>
<em>ok</em><br/>
<em>{error, Error}</em>
</p>
-<p>An error (preferably enotsup) is to be expected if the option is
-not supported by the io_server (like if an 'echo' option is sent in a
-setopt Request to a plain file).</p>
+<p>An error (preferably <c>enotsup</c>) is to be expected if the option is
+not supported by the I/O server (like if an <c>echo</c> option is sent in a
+<c>setopts</c> request to a plain file).</p>
-<p>To retrieve options, this message is used:</p>
+<p>To retrieve options, this request is used:</p>
<p>
<em>getopts</em>
</p>
-<p>The 'getopts' message requests a complete list of all options
-supported by the io_server as well as their current values.</p>
+<p>The <c>getopts</c> request asks for a complete list of all options
+supported by the I/O server as well as their current values.</p>
-<p>The server replies:</p>
+<p>The I/O server replies:</p>
<p>
<em>OptList</em><br/>
-<em>{error,Error}</em>
+<em>{error, Error}</em>
</p>
<list type="bulleted">
-<item>OptList is a list of tuples {Option, Value} where Option is always
+<item><c>OptList</c> is a list of tuples <c>{Option, Value}</c> where <c>Option</c> is always
an atom.</item>
</list>
</section>
<section>
-<title>Multiple I/O requests</title>
+<title>Multiple I/O Requests</title>
-<p>The Request element can in itself contain several Requests by using
+<p>The <c>Request</c> element can in itself contain several <c>Request</c>s by using
the following format:</p>
<p>
<em>{requests, Requests}</em>
</p>
<list type="bulleted">
-<item>Requests is a list of valid Request tuples for the protocol, they
+<item><c>Requests</c> is a list of valid <c>io_request</c> tuples for the protocol, they
shall be executed in the order in which they appear in the list and
the execution should continue until one of the requests result in an
error or the list is consumed. The result of the last request is
sent back to the client.</item>
</list>
-<p>The server can for a list of requests send any of the valid results in
+<p>The I/O server can for a list of requests send any of the valid results in
the reply:</p>
<p>
@@ -395,7 +401,7 @@ the reply:</p>
<p>- depending on the actual requests in the list.</p>
</section>
<section>
-<title>Optional I/O-requests</title>
+<title>Optional I/O Requests</title>
<p>The following I/O request is optional to implement and a client
should be prepared for an error return:</p>
@@ -403,47 +409,47 @@ should be prepared for an error return:</p>
<em>{get_geometry, Geometry}</em>
</p>
<list type="bulleted">
-<item>Geometry is either the atom 'rows' or the atom 'columns'.</item>
+<item><c>Geometry</c> is either the atom <c>rows</c> or the atom <c>columns</c>.</item>
</list>
-<p>The server should send the Reply as:</p>
+<p>The I/O server should send the <c>Reply</c> as:</p>
<p>
<em>{ok, N}</em><br/>
<em>{error, Error}</em>
</p>
<list type="bulleted">
-<item>N is the number of character rows or columns the device has, if
- applicable to the device the io_server handles, otherwise {error,
- enotsup} is a good answer.</item>
+<item><c>N</c> is the number of character rows or columns the IO device has, if
+ applicable to the IO device the I/O server handles, otherwise <c>{error,
+ enotsup}</c> is a good answer.</item>
</list>
</section>
<section>
-<title>Unimplemented request types:</title>
+<title>Unimplemented Request Types</title>
-<p>If an io_server encounters a request it does not recognize (i.e. the
-io_request tuple is in the expected format, but the actual Request is
-unknown), the server should send a valid reply with the error tuple:</p>
+<p>If an I/O server encounters a request it does not recognize (i.e. the
+<c>io_request</c> tuple is in the expected format, but the actual <c>Request</c> is
+unknown), the I/O server should send a valid reply with the error tuple:</p>
<p>
<em>{error, request}</em>
</p>
-<p>This makes it possible to extend the protocol with optional messages
+<p>This makes it possible to extend the protocol with optional requests
and for the clients to be somewhat backwards compatible.</p>
</section>
<section>
-<title>An annotated and working example io_server:</title>
+<title>An Annotated and Working Example I/O Server</title>
-<p>An io_server is any process capable of handling the protocol. There is
-no generic io_server behavior, but could well be. The framework is
+<p>An I/O server is any process capable of handling the I/O protocol. There is
+no generic I/O server behavior, but could well be. The framework is
simple enough, a process handling incoming requests, usually both
-io_requests and other device-specific requests (for i.e. positioning ,
+I/O-requests and other IO device-specific requests (for i.e. positioning,
closing etc.).</p>
-<p>Our example io_server stores characters in an ets table, making up a
+<p>Our example I/O server stores characters in an ETS table, making up a
fairly crude ram-file (it is probably not useful, but working).</p>
<p>The module begins with the usual directives, a function to start the
-server and a main loop handling the requests:</p>
+I/O server and a main loop handling the requests:</p>
<code>
-module(ets_io_server).
@@ -486,18 +492,19 @@ loop(State) -&gt;
</code>
<p>The main loop receives messages from the client (which might be using
-the io-module to send requests). For each request the function
-request/2 is called and a reply is eventually sent using the reply/3
+the <seealso marker="stdlib:io">io</seealso> module to send requests).
+For each request the function
+<c>request/2</c> is called and a reply is eventually sent using the <c>reply/3</c>
function.</p>
-<p>The &quot;private&quot; message {From, rewind} results in the
+<p>The &quot;private&quot; message <c>{From, rewind}</c> results in the
current position in the pseudo-file to be reset to 0 (the beginning of
-the &quot;file&quot;). This is a typical example of device-specific
+the &quot;file&quot;). This is a typical example of IO device-specific
messages not being part of the I/O-protocol. It is usually a bad idea
-to embed such private messages in io_request tuples, as that might be
+to embed such private messages in <c>io_request</c> tuples, as that might be
confusing to the reader.</p>
-<p>Let's look at the reply function first...</p>
+<p>Let us look at the reply function first...</p>
<code>
@@ -506,8 +513,8 @@ reply(From, ReplyAs, Reply) -&gt;
</code>
-<p>Simple enough, it sends the io_reply tuple back to the client,
-providing the ReplyAs element received in the request along with the
+<p>Simple enough, it sends the <c>io_reply</c> tuple back to the client,
+providing the <c>ReplyAs</c> element received in the request along with the
result of the request, as described above.</p>
<p>Now look at the different requests we need to handle. First the
@@ -525,18 +532,18 @@ request({put_chars, Encoding, Module, Function, Args}, State) -&gt;
end;
</code>
-<p>The Encoding tells us how the characters in the message are
+<p>The <c>Encoding</c> tells us how the characters in the request are
represented. We want to store the characters as lists in the
-ets-table, so we convert them to lists using the
-unicode:characters_to_list/2 function. The conversion function
-conveniently accepts the encoding types unicode or latin1, so we can
-use the Encoding parameter directly.</p>
+ETS table, so we convert them to lists using the
+<seealso marker="stdlib:unicode#characters_to_list/2"><c>unicode:characters_to_list/2</c></seealso> function. The conversion function
+conveniently accepts the encoding types <c>unicode</c> or <c>latin1</c>, so we can
+use <c>Encoding</c> directly.</p>
-<p>When Module, Function and Arguments are provided, we simply apply it
+<p>When <c>Module</c>, <c>Function</c> and <c>Arguments</c> are provided, we simply apply it
and do the same thing with the result as if the data was provided
directly.</p>
-<p>Let's handle the requests for retrieving data too:</p>
+<p>Let us handle the requests for retrieving data too:</p>
<code>
request({get_until, Encoding, _Prompt, M, F, As}, State) -&gt;
@@ -550,11 +557,11 @@ request({get_line, Encoding, _Prompt}, State) -&gt;
</code>
<p>Here we have cheated a little by more or less only implementing
-get_until and using internal helpers to implement get_chars and
-get_line. In production code, this might be to inefficient, but that
+<c>get_until</c> and using internal helpers to implement <c>get_chars</c> and
+<c>get_line</c>. In production code, this might be too inefficient, but that
of course depends on the frequency of the different requests. Before
-we start actually implementing the functions put_chars/2 and
-get_until/5, lets look into the few remaining requests:</p>
+we start actually implementing the functions <c>put_chars/2</c> and
+<c>get_until/5</c>, let us look into the few remaining requests:</p>
<code>
request({get_geometry,_}, State) -&gt;
@@ -567,18 +574,18 @@ request({requests, Reqs}, State) -&gt;
multi_request(Reqs, {ok, ok, State});
</code>
-<p>The get_geometry request has no meaning for this io_server, so the
-reply will be {error, enotsup}. The only option we handle is the
-binary/list option, which is done in separate functions.</p>
+<p>The <c>get_geometry</c> request has no meaning for this I/O server, so the
+reply will be <c>{error, enotsup}</c>. The only option we handle is the
+<c>binary</c>/<c>list</c> option, which is done in separate functions.</p>
-<p>The multi-request tag (requests) is handled in a separate loop
+<p>The multi-request tag (<c>requests</c>) is handled in a separate loop
function applying the requests in the list one after another,
returning the last result.</p>
-<p>What's left is to handle backward compatibility and the file-module
+<p>What is left is to handle backward compatibility and the <seealso marker="kernel:file">file</seealso> module
(which uses the old requests until backward compatibility with pre-R13
-nodes is no longer needed). Note that the io_server will not work with
-a simple file:write if these are not added:</p>
+nodes is no longer needed). Note that the I/O server will not work with
+a simple <c>file:write/2</c> if these are not added:</p>
<code>
request({put_chars,Chars}, State) -&gt;
@@ -593,7 +600,7 @@ request({get_until, Prompt,M,F,As}, State) -&gt;
request({get_until,latin1,Prompt,M,F,As}, State);
</code>
-<p>Ok, what's left now is to return {error, request} if the request is
+<p>OK, what is left now is to return <c>{error, request}</c> if the request is
not recognized:</p>
<code>
@@ -601,7 +608,7 @@ request(_Other, State) -&gt;
{error, {error, request}, State}.
</code>
-<p>Let's move further and actually handle the different requests, first
+<p>Let us move further and actually handle the different requests, first
the fairly generic multi-request type:</p>
<code>
@@ -615,10 +622,10 @@ multi_request([], Result) -&gt;
<p>We loop through the requests one at the time, stopping when we either
encounter an error or the list is exhausted. The last return value is
-sent back to the client (it's first returned to the main loop and then
-sent back by the function io_reply).</p>
+sent back to the client (it is first returned to the main loop and then
+sent back by the function <c>io_reply</c>).</p>
-<p>The getopt and setopt requests are also simple to handle, we just
+<p>The <c>getopts</c> and <c>setopts</c> requests are also simple to handle, we just
change or read our state record:</p>
<code>
@@ -656,24 +663,24 @@ getopts(#state{mode=M} = S) -&gt;
end}],S}.
</code>
-<p>As a convention, all io_servers handle both {setopts, [binary]},
-{setopts, [list]} and {setopts,[{binary, bool()}]}, hence the trick
-with proplists:substitute_negations/2 and proplists:unfold/1. If
-invalid options are sent to us, we send {error,enotsup} back to the
+<p>As a convention, all I/O servers handle both <c>{setopts, [binary]}</c>,
+<c>{setopts, [list]}</c> and <c>{setopts,[{binary, boolean()}]}</c>, hence the trick
+with <c>proplists:substitute_negations/2</c> and <c>proplists:unfold/1</c>. If
+invalid options are sent to us, we send <c>{error, enotsup}</c> back to the
client.</p>
-<p>The getopts request should return a list of {Option, Value} tuples,
+<p>The <c>getopts</c> request should return a list of <c>{Option, Value}</c> tuples,
which has the twofold function of providing both the current values
-and the available options of this io_server. We have only one option,
+and the available options of this I/O server. We have only one option,
and hence return that.</p>
-<p>So far our io_server has been fairly generic (except for the rewind
-request handled in the main loop and the creation of an ets table).
-Most io_servers contain code similar to what's above.</p>
+<p>So far our I/O server has been fairly generic (except for the <c>rewind</c>
+request handled in the main loop and the creation of an ETS table).
+Most I/O servers contain code similar to the one above.</p>
<p>To make the example runnable, we now start implementing the actual
-reading and writing of the data to/from the ets-table. First the
-put_chars function:</p>
+reading and writing of the data to/from the ETS table. First the
+<c>put_chars/3</c> function:</p>
<code>
put_chars(Chars, #state{table = T, position = P} = State) -&gt;
@@ -686,10 +693,10 @@ put_chars(Chars, #state{table = T, position = P} = State) -&gt;
<p>We already have the data as (Unicode) lists and therefore just split
the list in runs of a predefined size and put each run in the
table at the current position (and forward). The functions
-split_data/3 and apply_update/2 are implemented below.</p>
+<c>split_data/3</c> and <c>apply_update/2</c> are implemented below.</p>
-<p>Now we want to read data from the table. The get_until function reads
-data and applies the function until it says it's done. The result is
+<p>Now we want to read data from the table. The <c>get_until/5</c> function reads
+data and applies the function until it says it is done. The result is
sent back to the client:</p>
<code>
@@ -700,11 +707,12 @@ get_until(Encoding, Mod, Func, As,
if
M =:= binary -&gt;
{ok,
- unicode:characters_to_binary(Data,unicode,Encoding),
+ unicode:characters_to_binary(Data, unicode, Encoding),
State#state{position = NewP}};
true -&gt;
case check(Encoding,
- unicode:characters_to_list(Data, unicode)) of
+ unicode:characters_to_list(Data, unicode))
+ of
{error, _} = E -&gt;
{error, E, State};
List -&gt;
@@ -730,24 +738,24 @@ get_loop(M,F,A,T,P,C) -&gt;
end.
</code>
-<p>Here we also handle the mode (binary or list) that can be set by
-the setopts request. By default, all OTP io_servers send data back to
-the client as lists, but switching mode to binary might increase
-efficiency if the server handles it in an appropriate way. The
-implementation of get_until is hard to get efficient as the supplied
-function is defined to take lists as arguments, but get_chars and
-get_line can be optimized for binary mode. This example does not
+<p>Here we also handle the mode (<c>binary</c> or <c>list</c>) that can be set by
+the <c>setopts</c> request. By default, all OTP I/O servers send data back to
+the client as lists, but switching mode to <c>binary</c> might increase
+efficiency if the I/O server handles it in an appropriate way. The
+implementation of <c>get_until</c> is hard to get efficient as the supplied
+function is defined to take lists as arguments, but <c>get_chars</c> and
+<c>get_line</c> can be optimized for binary mode. This example does not
optimize anything however. It is important though that the returned
data is of the right type depending on the options set, so we convert
the lists to binaries in the correct encoding <em>if possible</em>
-before returning. The function supplied in the get_until request may,
+before returning. The function supplied in the <c>get_until</c> request tuple may,
as its final result return anything, so only functions actually
returning lists can get them converted to binaries. If the request
-contained the encoding tag unicode, the lists can contain all unicode
+contained the encoding tag <c>unicode</c>, the lists can contain all Unicode
codepoints and the binaries should be in UTF-8, if the encoding tag
-was latin1, the client should only get characters in the range
-0..255. The function check/2 takes care of not returning arbitrary
-unicode codepoints in lists if the encoding was given as latin1. If
+was <c>latin1</c>, the client should only get characters in the range
+0..255. The function <c>check/2</c> takes care of not returning arbitrary
+Unicode codepoints in lists if the encoding was given as <c>latin1</c>. If
the function did not return a list, the check cannot be performed and
the result will be that of the supplied function untouched.</p>
@@ -768,13 +776,13 @@ check(latin1, List) -&gt;
end.
</code>
-<p>The function check takes care of providing an error tuple if unicode
+<p>The function check takes care of providing an error tuple if Unicode
codepoints above 255 is to be returned if the client requested
latin1.</p>
-<p>The two functions until_newline/3 and until_enough/3 are helpers used
-together with the get_until function to implement get_chars and
-get_line (inefficiently):</p>
+<p>The two functions <c>until_newline/3</c> and <c>until_enough/3</c> are helpers used
+together with the <c>get_until/5</c> function to implement <c>get_chars</c> and
+<c>get_line</c> (inefficiently):</p>
<code>
until_newline([],eof,_MyStopCharacter) -&gt;
@@ -782,7 +790,9 @@ until_newline([],eof,_MyStopCharacter) -&gt;
until_newline(ThisFar,eof,_MyStopCharacter) -&gt;
{done,ThisFar,[]};
until_newline(ThisFar,CharList,MyStopCharacter) -&gt;
- case lists:splitwith(fun(X) -&gt; X =/= MyStopCharacter end, CharList) of
+ case
+ lists:splitwith(fun(X) -&gt; X =/= MyStopCharacter end, CharList)
+ of
{L,[]} -&gt;
{more,ThisFar++L};
{L2,[MyStopCharacter|Rest]} -&gt;
@@ -802,10 +812,10 @@ until_enough(ThisFar,CharList,_N) -&gt;
</code>
<p>As can be seen, the functions above are just the type of functions
-that should be provided in get_until requests.</p>
+that should be provided in <c>get_until</c> requests.</p>
<p>Now we only need to read and write the table in an appropriate way to
-complete the server:</p>
+complete the I/O server:</p>
<code>
get(P,Tab) -&gt;
@@ -847,13 +857,13 @@ apply_update(Table, {Row, Col, List}) -&gt;
end.
</code>
-<p>The table is read or written in chunks of ?CHARS_PER_REC, overwriting
+<p>The table is read or written in chunks of <c>?CHARS_PER_REC</c>, overwriting
when necessary. The implementation is obviously not efficient, it is
just working.</p>
<p>This concludes the example. It is fully runnable and you can read or
-write to the io_server by using i.e. the io_module or even the file
-module. It's as simple as that to implement a fully fledged io_server
+write to the I/O server by using i.e. the <seealso marker="stdlib:io">io</seealso> module or even the <seealso marker="kernel:file">file</seealso>
+module. It is as simple as that to implement a fully fledged I/O server
in Erlang.</p>
</section>
</chapter>
diff --git a/lib/stdlib/doc/src/proplists.xml b/lib/stdlib/doc/src/proplists.xml
index 225c5e97eb..8d64319344 100644
--- a/lib/stdlib/doc/src/proplists.xml
+++ b/lib/stdlib/doc/src/proplists.xml
@@ -70,7 +70,7 @@
<fsummary></fsummary>
<desc>
<p>Minimizes the representation of all entries in the list. This is
- equivalent to <c><![CDATA[[property(P) || P <- List]]]></c>.</p>
+ equivalent to <c><![CDATA[[property(P) || P <- ListIn]]]></c>.</p>
<p>See also: <c>property/1</c>, <c>unfold/1</c>.</p>
</desc>
</func>
@@ -88,11 +88,11 @@
<desc>
<p>Expands particular properties to corresponding sets of
properties (or other terms). For each pair <c>{<anno>Property</anno>, <anno>Expansion</anno>}</c> in <c><anno>Expansions</anno></c>, if <c>E</c> is
- the first entry in <c><anno>List</anno></c> with the same key as
+ the first entry in <c><anno>ListIn</anno></c> with the same key as
<c><anno>Property</anno></c>, and <c>E</c> and <c><anno>Property</anno></c>
have equivalent normal forms, then <c>E</c> is replaced with
the terms in <c><anno>Expansion</anno></c>, and any following entries with
- the same key are deleted from <c><anno>List</anno></c>.</p>
+ the same key are deleted from <c><anno>ListIn</anno></c>.</p>
<p>For example, the following expressions all return <c>[fie, bar, baz, fum]</c>:</p>
<code type="none">
expand([{foo, [bar, baz]}],
@@ -198,7 +198,7 @@
<name name="normalize" arity="2"/>
<fsummary></fsummary>
<desc>
- <p>Passes <c><anno>List</anno></c> through a sequence of
+ <p>Passes <c><anno>ListIn</anno></c> through a sequence of
substitution/expansion stages. For an <c>aliases</c> operation,
the function <c>substitute_aliases/2</c> is applied using the
given list of aliases; for a <c>negations</c> operation,
@@ -221,9 +221,9 @@
<fsummary></fsummary>
<desc>
<p>Creates a normal form (minimal) representation of a property. If
- <c><anno>Property</anno></c> is <c>{Key, true}</c> where <c>Key</c> is
- an atom, this returns <c>Key</c>, otherwise the whole term
- <c><anno>Property</anno></c> is returned.</p>
+ <c><anno>PropertyIn</anno></c> is <c>{Key, true}</c> where
+ <c>Key</c> is an atom, this returns <c>Key</c>, otherwise
+ the whole term <c><anno>PropertyIn</anno></c> is returned.</p>
<p>See also: <c>property/2</c>.</p>
</desc>
</func>
@@ -260,7 +260,7 @@
<fsummary></fsummary>
<desc>
<p>Substitutes keys of properties. For each entry in
- <c><anno>List</anno></c>, if it is associated with some key <c>K1</c>
+ <c><anno>ListIn</anno></c>, if it is associated with some key <c>K1</c>
such that <c>{K1, K2}</c> occurs in <c><anno>Aliases</anno></c>, the
key of the entry is changed to <c>K2</c>. If the same
<c>K1</c> occurs more than once in <c><anno>Aliases</anno></c>, only
@@ -278,13 +278,13 @@
<desc>
<p>Substitutes keys of boolean-valued properties and
simultaneously negates their values. For each entry in
- <c><anno>List</anno></c>, if it is associated with some key <c>K1</c>
+ <c><anno>ListIn</anno></c>, if it is associated with some key <c>K1</c>
such that <c>{K1, K2}</c> occurs in <c><anno>Negations</anno></c>, then
if the entry was <c>{K1, true}</c> it will be replaced with
<c>{K2, false}</c>, otherwise it will be replaced with
<c>{K2, true}</c>, thus changing the name of the option and
simultaneously negating the value given by
- <c>get_bool(List)</c>. If the same <c>K1</c> occurs more
+ <c>get_bool(ListIn)</c>. If the same <c>K1</c> occurs more
than once in <c><anno>Negations</anno></c>, only the first occurrence is
used.</p>
<p>Example: <c>substitute_negations([{no_foo, foo}], L)</c>
@@ -300,7 +300,7 @@
<name name="unfold" arity="1"/>
<fsummary></fsummary>
<desc>
- <p>Unfolds all occurrences of atoms in <c><anno>List</anno></c> to tuples
+ <p>Unfolds all occurrences of atoms in <c><anno>ListIn</anno></c> to tuples
<c>{Atom, true}</c>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml
index 2211bfb925..71a6e34513 100644
--- a/lib/stdlib/doc/src/re.xml
+++ b/lib/stdlib/doc/src/re.xml
@@ -96,12 +96,12 @@
subjects during the program's lifetime. Compiling once and
executing many times is far more efficient than compiling each
time one wants to match.</p>
- <p>When the unicode option is given, the regular expression should be given as a valid unicode <c>charlist()</c>, otherwise as any valid <c>iodata()</c>.</p>
+ <p>When the unicode option is given, the regular expression should be given as a valid Unicode <c>charlist()</c>, otherwise as any valid <c>iodata()</c>.</p>
<p><marker id="compile_options"/>The options have the following meanings:</p>
<taglist>
<tag><c>unicode</c></tag>
- <item>The regular expression is given as a unicode <c>charlist()</c> and the resulting regular expression code is to be run against a valid unicode <c>charlist()</c> subject.</item>
+ <item>The regular expression is given as a Unicode <c>charlist()</c> and the resulting regular expression code is to be run against a valid Unicode <c>charlist()</c> subject.</item>
<tag><c>anchored</c></tag>
<item>The pattern is forced to be "anchored", that is, it is constrained to match only at the first matching point in the string that is being searched (the "subject string"). This effect can also be achieved by appropriate constructs in the pattern itself.</item>
<tag><c>caseless</c></tag>
@@ -478,7 +478,7 @@ This option makes it possible to include comments inside complicated patterns. N
<p>Replaces the matched part of the <c><anno>Subject</anno></c> string with the contents of <c><anno>Replacement</anno></c>.</p>
<p>The permissible options are the same as for <c>re:run/3</c>, except that the <c>capture</c> option is not allowed.
Instead a <c>{return, <anno>ReturnType</anno>}</c> is present. The default return type is <c>iodata</c>, constructed in a
- way to minimize copying. The <c>iodata</c> result can be used directly in many i/o-operations. If a flat <c>list()</c> is
+ way to minimize copying. The <c>iodata</c> result can be used directly in many I/O-operations. If a flat <c>list()</c> is
desired, specify <c>{return, list}</c> and if a binary is preferred, specify <c>{return, binary}</c>.</p>
<p>As in the <c>re:run/3</c> function, an <c>mp()</c> compiled
diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml
index 1f6cbaccd7..d235f3e180 100644
--- a/lib/stdlib/doc/src/unicode.xml
+++ b/lib/stdlib/doc/src/unicode.xml
@@ -32,9 +32,9 @@
<module>unicode</module>
<modulesummary>Functions for converting Unicode characters</modulesummary>
<description>
- <p>This module contains functions for converting between different character representations. Basically it converts between iso-latin-1 characters and Unicode ditto, but it can also convert between different Unicode encodings (like UTF-8, UTF-16 and UTF-32).</p>
+ <p>This module contains functions for converting between different character representations. Basically it converts between ISO-latin-1 characters and Unicode ditto, but it can also convert between different Unicode encodings (like UTF-8, UTF-16 and UTF-32).</p>
<p>The default Unicode encoding in Erlang is in binaries UTF-8, which is also the format in which built in functions and libraries in OTP expect to find binary Unicode data. In lists, Unicode data is encoded as integers, each integer representing one character and encoded simply as the Unicode codepoint for the character.</p>
- <p>Other Unicode encodings than integers representing codepoints or UTF-8 in binaries are referred to as &quot;external encodings&quot;. The iso-latin-1 encoding is in binaries and lists referred to as latin1-encoding.</p>
+ <p>Other Unicode encodings than integers representing codepoints or UTF-8 in binaries are referred to as &quot;external encodings&quot;. The ISO-latin-1 encoding is in binaries and lists referred to as latin1-encoding.</p>
<p>It is recommended to only use external encodings for communication with external entities where this is required. When working inside the Erlang/OTP environment, it is recommended to keep binaries in UTF-8 when representing Unicode characters. Latin1 encoding is supported both for backward compatibility and for communication with external entities not supporting Unicode character sets.</p>
</description>
@@ -48,13 +48,13 @@
<datatype>
<name name="unicode_binary"/>
<desc>
- <p>A binary() with characters encoded in the UTF-8 coding standard.</p>
+ <p>A <c>binary()</c> with characters encoded in the UTF-8 coding standard.</p>
</desc>
</datatype>
<datatype>
<name name="unicode_char"/>
<desc>
- <p>An integer() representing a valid unicode codepoint.</p>
+ <p>An <c>integer()</c> representing a valid Unicode codepoint.</p>
</desc>
</datatype>
<datatype>
@@ -63,7 +63,7 @@
<datatype>
<name name="charlist"/>
<desc>
- <p>A unicode_binary is allowed as the tail of the list.</p>
+ <p>A <c>unicode_binary()</c> is allowed as the tail of the list.</p>
</desc>
</datatype>
<datatype>
@@ -85,7 +85,7 @@
</datatype>
<datatype>
<name name="latin1_binary"/>
- <desc><p>A <c>binary()</c> with characters coded in iso-latin-1.</p>
+ <desc><p>A <c>binary()</c> with characters coded in ISO-latin-1.</p>
</desc>
</datatype>
<datatype>
@@ -110,7 +110,9 @@
<name name="bom_to_encoding" arity="1"/>
<fsummary>Identify UTF byte order marks in a binary.</fsummary>
<type name="endian"/>
- <type_desc variable="Bin">A binary() of byte_size 4 or more.</type_desc>
+ <type_desc variable="Bin">
+ A <c>binary()</c> such that <c>byte_size(<anno>Bin</anno>) >= 4</c>.
+ </type_desc>
<desc>
<p>Check for a UTF byte order mark (BOM) in the beginning of a
@@ -126,7 +128,7 @@
<name name="characters_to_list" arity="1"/>
<fsummary>Convert a collection of characters to list of Unicode characters</fsummary>
<desc>
- <p>Same as characters_to_list(<anno>Data</anno>,unicode).</p>
+ <p>Same as <c>characters_to_list(<anno>Data</anno>, unicode)</c>.</p>
</desc>
</func>
<func>
@@ -134,8 +136,8 @@
<fsummary>Convert a collection of characters to list of Unicode characters</fsummary>
<desc>
- <p>This function converts a possibly deep list of integers and
- binaries into a list of integers representing unicode
+ <p>Converts a possibly deep list of integers and
+ binaries into a list of integers representing Unicode
characters. The binaries in the input may have characters
encoded as latin1 (0 - 255, one character per byte), in which
case the <c><anno>InEncoding</anno></c> parameter should be given as
@@ -148,18 +150,18 @@
<p>If <c><anno>InEncoding</anno></c> is <c>latin1</c>, the <c><anno>Data</anno></c> parameter
corresponds to the <c>iodata()</c> type, but for <c>unicode</c>,
the <c><anno>Data</anno></c> parameter can contain integers greater than 255
- (unicode characters beyond the iso-latin-1 range), which would
+ (Unicode characters beyond the ISO-latin-1 range), which would
make it invalid as <c>iodata()</c>.</p>
<p>The purpose of the function is mainly to be able to convert
- combinations of unicode characters into a pure unicode
+ combinations of Unicode characters into a pure Unicode
string in list representation for further processing. For
writing the data to an external entity, the reverse function
<seealso
- marker="#characters_to_binary/3">characters_to_binary/3</seealso>
+ marker="#characters_to_binary/3"><c>characters_to_binary/3</c></seealso>
comes in handy.</p>
- <p>The option <c>unicode</c> is an alias for <c>utf8</c>, as this is the
+ <p>The option <c>unicode</c> is an alias for <c>utf8</c>, as this is the
preferred encoding for Unicode characters in
binaries. <c>utf16</c> is an alias for <c>{utf16,big}</c> and
<c>utf32</c> is an alias for <c>{utf32,big}</c>. The <c>big</c>
@@ -167,7 +169,7 @@
encoding.</p>
<p>If for some reason, the data cannot be converted, either
- because of illegal unicode/latin1 characters in the list, or
+ because of illegal Unicode/latin1 characters in the list, or
because of invalid UTF encoding in any binaries, an error
tuple is returned. The error tuple contains the tag
<c>error</c>, a list representing the characters that could be
@@ -176,7 +178,7 @@
last part is mostly for debugging as it still constitutes a
possibly deep and/or mixed list, not necessarily of the same
depth as the original data. The error occurs when traversing the
- list and whatever's left to decode is simply returned as is.</p>
+ list and whatever is left to decode is simply returned as is.</p>
<p>However, if the input <c><anno>Data</anno></c> is a pure binary, the third
part of the error tuple is guaranteed to be a binary as
@@ -191,7 +193,7 @@
of a Unicode type, an error occurs whenever an integer
<list type="bulleted">
<item>greater than <c>16#10FFFF</c>
- (the maximum unicode character),</item>
+ (the maximum Unicode character),</item>
<item>in the range <c>16#D800</c> to <c>16#DFFF</c>
(invalid range reserved for UTF-16 surrogate pairs)</item>
</list>
@@ -205,14 +207,14 @@
(like the upper
bits of the bytes being wrong), the bytes are decoded to a
too large number, the bytes are decoded to a code-point in the
- invalid unicode
- range or encoding is &quot;overlong&quot;, meaning that a
+ invalid Unicode
+ range, or encoding is &quot;overlong&quot;, meaning that a
number should have been encoded in fewer bytes. The
case of a truncated UTF is handled specially, see the
paragraph about incomplete binaries below. If
<c><anno>InEncoding</anno></c> is <c>latin1</c>, binaries are always valid
as long as they contain whole bytes,
- as each byte falls into the valid iso-latin-1 range.</item>
+ as each byte falls into the valid ISO-latin-1 range.</item>
</list>
@@ -250,7 +252,7 @@
ever be decoded.</p>
<p>If any parameters are of the wrong type, the list structure
- is invalid (a number as tail) or the binaries does not contain
+ is invalid (a number as tail) or the binaries do not contain
whole bytes (bit-strings), a <c>badarg</c> exception is
thrown.</p>
@@ -258,28 +260,27 @@
</func>
<func>
<name name="characters_to_binary" arity="1"/>
- <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary>
+ <fsummary>Convert a collection of characters to a UTF-8 binary</fsummary>
<desc>
- <p>Same as characters_to_binary(Data, unicode, unicode).</p>
+ <p>Same as <c>characters_to_binary(<anno>Data</anno>, unicode, unicode)</c>.</p>
</desc>
</func>
<func>
<name name="characters_to_binary" arity="2"/>
- <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary>
+ <fsummary>Convert a collection of characters to a UTF-8 binary</fsummary>
<desc>
- <p>Same as characters_to_binary(<anno>Data</anno>, <anno>InEncoding</anno>, unicode).</p>
+ <p>Same as <c>characters_to_binary(<anno>Data</anno>, <anno>InEncoding</anno>, unicode)</c>.</p>
</desc>
</func>
<func>
<name name="characters_to_binary" arity="3"/>
- <fsummary>Convert a collection of characters to an UTF-8 binary</fsummary>
+ <fsummary>Convert a collection of characters to a UTF-8 binary</fsummary>
<desc>
- <p>This function behaves as <seealso
- marker="#characters_to_list/2">
- characters_to_list/2</seealso>, but produces an binary
- instead of a unicode list. The
+ <p>Behaves as <seealso marker="#characters_to_list/2">
+ <c>characters_to_list/2</c></seealso>, but produces an binary
+ instead of a Unicode list. The
<c><anno>InEncoding</anno></c> defines how input is to be interpreted if
binaries are present in the <c>Data</c>, while
<c><anno>OutEncoding</anno></c> defines in what format output is to be
@@ -294,7 +295,7 @@
<p>Errors and exceptions occur as in <seealso
marker="#characters_to_list/2">
- characters_to_list/2</seealso>, but the second element
+ <c>characters_to_list/2</c></seealso>, but the second element
in the <c>error</c> or
<c>incomplete</c> tuple will be a <c>binary()</c> and not a
<c>list()</c>.</p>
@@ -304,16 +305,18 @@
<func>
<name name="encoding_to_bom" arity="1"/>
<fsummary>Create a binary UTF byte order mark from encoding.</fsummary>
- <type_desc variable="Bin">A binary() of byte_size 4 or more.</type_desc>
+ <type_desc variable="Bin">
+ A <c>binary()</c> such that <c>byte_size(<anno>Bin</anno>) >= 4</c>.
+ </type_desc>
<desc>
- <p>Create an UTF byte order mark (BOM) as a binary from the
+ <p>Create a UTF byte order mark (BOM) as a binary from the
supplied <c><anno>InEncoding</anno></c>. The BOM is, if supported at all,
expected to be placed first in UTF encoded files or
messages.</p>
<p>The function returns <c>&lt;&lt;&gt;&gt;</c> for the
- <c>latin1</c> encoding, there is no BOM for ISO-latin-1.</p>
+ <c>latin1</c> encoding as there is no BOM for ISO-latin-1.</p>
<p>It can be noted that the BOM for UTF-8 is seldom used, and it
is really not a <em>byte order</em> mark. There are obviously no
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index bbcd49a934..320b5b2e84 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="utf8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
@@ -33,14 +33,14 @@
<file>unicode_usage.xml</file>
</header>
<p>Implementing support for Unicode character sets is an ongoing process. The Erlang Enhancement Proposal (EEP) 10 outlines the basics of Unicode support and also specifies a default encoding in binaries that all Unicode-aware modules should handle in the future.</p>
-<p>The functionality described in EEP10 is implemented in Erlang/OTP as of R13A, but that's by no means the end of it. More functionality will be needed in the future and more OTP-libraries might need updating to cope with Unicode data. One example of future development is obvious when reading this manual, our documentation format is limited to the ISO-latin-1 character range, why no Unicode characters beyond that range will occur in this document.</p>
+<p>The functionality described in EEP10 is implemented in Erlang/OTP as of R13A, but that is by no means the end of it. More functionality will be needed in the future and more OTP-libraries might need updating to cope with Unicode data.</p>
<p>This guide outlines the current Unicode support and gives a couple of recipes for working with Unicode data.</p>
<section>
-<title>What Unicode is</title>
+<title>What Unicode Is</title>
<p>Unicode is a standard defining codepoints (numbers) for all known, living or dead, scripts. In principle, every known symbol used in any language has a Unicode codepoint.</p>
<p>Unicode codepoints are defined and published by the <em>Unicode Consortium</em>, which is a non profit organization.</p>
<p>Support for Unicode is increasing throughout the world of computing, as the benefits of one common character set are overwhelming when programs are used in a global environment.</p>
-<p>Along with the base of the standard, the codepoints for all the scripts, there are a couple of encoding standards available. Different operating systems and tools support different encodings. For example Linux and MacOS X has chosen the UTF-8 encoding, which is backwards compatible with 7-bit ASCII and therefore affects programs written in plain English the least. Windows&reg; on the other hand supports a limited version of UTF-16, namely all the code planes where the characters can be stored in one single 16-bit entity, which includes most living languages.</p>
+<p>Along with the base of the standard, the codepoints for all the scripts, there are a couple of encoding standards available. Different operating systems and tools support different encodings. For example Linux and MacOSX has chosen the UTF-8 encoding, which is backwards compatible with 7-bit ASCII and therefore affects programs written in plain English the least. Windows&reg; on the other hand supports a limited version of UTF-16, namely all the code planes where the characters can be stored in one single 16-bit entity, which includes most living languages.</p>
<p>The most widely spread encodings are:</p>
<taglist>
<tag>UTF-8</tag>
@@ -56,38 +56,47 @@
<p>Additionally, the codepoint 16#FEFF is used for byte order marks (BOM's) and use of that character is not encouraged in other contexts than that. It actually is valid though, as the character "ZWNBS" (Zero Width Non Breaking Space). BOM's are used to identify encodings and byte order for programs where such parameters are not known in advance. Byte order marks are more seldom used than one could expect, but their use is becoming more widely spread as they provide the means for programs to make educated guesses about the Unicode format of a certain file.</p>
</section>
<section>
-<title>Standard Unicode representation in Erlang</title>
+<title>Standard Unicode Representation in Erlang</title>
<p>In Erlang, strings are actually lists of integers. A string is defined to be encoded in the ISO-latin-1 (ISO8859-1) character set, which is, codepoint by codepoint, a sub-range of the Unicode character set.</p>
<p>The standard list encoding for strings is therefore easily extendible to cope with the whole Unicode range: A Unicode string in Erlang is simply a list containing integers, each integer being a valid Unicode codepoint and representing one character in the Unicode character set.</p>
-<p>Regular Erlang strings in ISO-latin-1 are a subset of their Unicode strings.</p>
+<p>Regular Erlang strings in ISO-latin-1 are a subset of their Unicode
+strings.</p>
-<p>Binaries on the other hand are more troublesome. For performance reasons, programs often store textual data in binaries instead of lists, mainly because they are more compact (one byte per character instead of two words per character, as is the case with lists). Using erlang:list_to_binary/1, an regular Erlang string can be converted into a binary, effectively using the ISO-latin-1 encoding in the binary - one byte per character. This is very convenient for those regular Erlang strings, but cannot be done for Unicode lists.</p>
+<p>Binaries on the other hand are more troublesome. For performance reasons, programs often store textual data in binaries instead of lists, mainly because they are more compact (one byte per character instead of two words per character, as is the case with lists). Using <c>erlang:list_to_binary/1</c>, a regular Erlang string can be converted into a binary, effectively using the ISO-latin-1 encoding in the binary - one byte per character. This is very convenient for those regular Erlang strings, but cannot be done for Unicode lists.</p>
<p>As the UTF-8 encoding is widely spread and provides the most compact storage, it is selected as the standard encoding of Unicode characters in binaries for Erlang.</p>
<p>The standard binary encoding is used whenever a library function in Erlang should cope with Unicode data in binaries, but is of course not enforced when communicating externally. Functions and bit-syntax exist to encode and decode both UTF-8, UTF-16 and UTF-32 in binaries. Library functions dealing with binaries and Unicode in general, however, only deal with the default encoding.</p>
-<p>Character data may be combined from several sources, sometimes available in a mix of strings and binaries. Erlang has for long had the concept of iodata or iolists, where binaries and lists can be combined to represent a sequence of bytes. In the same way, the Unicode aware modules often allow for combinations of binaries and lists where the binaries have characters encoded in UTF-8 and the lists contain such binaries or numbers representing Unicode codepoints:</p>
+<p>Character data may be combined from several sources, sometimes available in a mix of strings and binaries. Erlang has for long had the concept of <c>iodata</c> or <c>iolists</c>, where binaries and lists can be combined to represent a sequence of bytes. In the same way, the Unicode aware modules often allow for combinations of binaries and lists where the binaries have characters encoded in UTF-8 and the lists contain such binaries or numbers representing Unicode codepoints:</p>
<code type="none">
unicode_binary() = binary() with characters encoded in UTF-8 coding standard
-unicode_char() = integer() representing valid unicode codepoint
+unicode_char() = integer() >= 0 representing valid Unicode codepoint
chardata() = charlist() | unicode_binary()
charlist() = [unicode_char() | unicode_binary() | charlist()]
a unicode_binary is allowed as the tail of the list</code>
-<p>The module <c>unicode</c> in stdlib even supports similar mixes with binaries containing other encodings than UTF-8, but that is a special case to allow for conversions to and from external data:</p>
+<p>The module <c>unicode</c> in STDLIB even supports similar mixes with binaries containing other encodings than UTF-8, but that is a special case to allow for conversions to and from external data:</p>
<code type="none">
-external_unicode_binary() = binary() with characters coded in a user specified Unicode
- encoding other than UTF-8 (UTF-16 or UTF-32)
+external_unicode_binary() = binary() with characters coded in
+ a user specified Unicode encoding other than UTF-8 (UTF-16 or UTF-32)
external_chardata() = external_charlist() | external_unicode_binary()
-external_charlist() = [unicode_char() | external_unicode_binary() | external_charlist()]
- an external_unicode_binary is allowed as the tail of the list</code>
+external_charlist() = [unicode_char() |
+ external_unicode_binary() |
+ external_charlist()]
+ an external_unicode_binary() is allowed as the tail of the list</code>
</section>
<section>
-<title>Basic language support for Unicode</title>
-<p>First of all, Erlang is still defined to be written in the ISO-latin-1 character set. Functions have to be named in that character set, atoms are restricted to ISO-latin-1 and regular strings are still lists of characters 0..255 in the ISO-latin-1 encoding. This has not (yet) changed, but the language has been slightly extended to cope with Unicode characters and encodings.</p>
-
+<title>Basic Language Support for Unicode</title>
+<p><marker id="unicode_in_erlang"/>As of Erlang/OTP R16 Erlang can be
+written in ISO-latin-1 or Unicode (UTF-8). The details on how to state
+the encoding of an Erlang source file can be found in <seealso
+marker="stdlib:epp#encoding">epp(3)</seealso>. Strings and comments
+can be written using Unicode, but functions still have to be named in
+ISO-latin-1 and atoms are restricted to ISO-latin-1. Erlang/OTP R18 is
+expected to handle functions named in Unicode as well as Unicode
+atoms.</p>
<section>
<title>Bit-syntax</title>
<p>The bit-syntax contains types for coping with binary data in the three main encodings. The types are named <c>utf8</c>, <c>utf16</c> and <c>utf32</c> respectively. The <c>utf16</c> and <c>utf32</c> types can be in a big- or little-endian variant:</p>
@@ -101,74 +110,79 @@ Bin3 = &lt;&lt;$H/utf32-little, $e/utf32-little, $l/utf32-little, $l/utf32-littl
Bin4 = &lt;&lt;"Hello"/utf16&gt;&gt;,</code>
</section>
<section>
-<title>String- and character-literals</title>
-<warning>
-<p>The literal syntax described here may be subject to change in R13B, it has not yet passed the usual process for language changes approval.</p>
-</warning>
-<p>It is convenient to be able to write a list of Unicode characters in the string syntax. However, the language specifies strings as being in the ISO-latin-1 character set which the compiler tool chain as well as many other tools expect.</p>
-<p>Also the source code is (for now) still expected to be written using the ISO-latin-1 character set, why Unicode characters beyond that range cannot be entered in string literals.</p>
-<p>To make it easier to enter Unicode characters in the shell, it allows strings with Unicode characters on input, immediately converting them to regular lists of integers. They will, by the evaluator etc be viewed as if they were input using the regular list syntax, which is - in the end - how the language actually treats them. They will in the same way not be output as strings by i.e <c>io:write/2</c> or <c>io:format/3</c> unless the format string supplied to <c>io:format</c> uses the Unicode translation modifier (which we will talk about later).</p>
-<p>For source code, there is an extension to the \OOO (backslash followed by three octal numbers) and \xHH (backslash followed by 'x', followed by two hexadecimal characters) syntax, namely \x{H ...} (a backslash followed by an 'x', followed by left curly bracket, any number of hexadecimal digits and a terminating right curly bracket). This allows for entering characters of any codepoint literally in a string. The string is immediately converted into a list by the scanner however, which is obvious when calling it directly:</p>
-<pre>
-1> <input>erl_scan:string("\"X\".").</input>
-{ok,[{string,1,"X"},{dot,1}],1}
-2> <input>erl_scan:string("\"\x{400}\".").</input>
-{ok,[{'[',1},{integer,1,1024},{']',1},{dot,1}],1}</pre>
-<p>Character literals, or rather integers representing Unicode codepoints can be expressed in a similar way using $\x{H ...}:</p>
-<pre>
-4> <input>$\x{400}.</input>
-1024</pre>
-<p>This also is a translation by the scanner:</p>
-<pre>
-5> <input>erl_scan:string("$Y.").</input>
-{ok,[{char,1,89},{dot,1}],1}
-6> <input>erl_scan:string("$\x{400}.").</input>
-{ok,[{integer,1,1024},{dot,1}],1}</pre>
-<p>In the shell, if using a Unicode input device, '$' can be followed directly by a Unicode character producing an integer. In the following example, let's imagine the character 'c' is actually a Cyrillic 's' (looking fairly similar):</p>
+<title>String- and Character-literals</title>
+<p>For source code, there is an extension to the <c>\</c>OOO (backslash
+followed by three octal numbers) and <c>\x</c>HH (backslash followed by <c>x</c>,
+followed by two hexadecimal characters) syntax, namely <c>\x{</c>H ...<c>}</c> (a
+backslash followed by an <c>x</c>, followed by left curly bracket, any
+number of hexadecimal digits and a terminating right curly bracket).
+This allows for entering characters of any codepoint literally in a
+string even when the encoding is ISO-latin-1.</p>
+</section>
+<p>In the shell, if using a Unicode input device, <c>$</c> can be followed directly by a Unicode character producing an integer. In the following example the codepoint of a Cyrillic <c>s</c> is output:</p>
<pre>
-7> <input>$c.</input>
+7> <input>$с.</input>
1089</pre>
</section>
-<p>The literal syntax allowing Unicode characters is to be viewed as "syntactic sugar", but is, as such, fairly useful.</p>
-</section>
<section>
-<title>The interactive shell</title>
+<title>The Interactive Shell</title>
<p>The interactive Erlang shell, when started towards a terminal or started using the <c>werl</c> command on windows, can support Unicode input and output.</p>
-<p>On Windows&reg;, proper operation requires that a suitable font is installed and selected for the Erlang application to use. If no suitable font is available on your system, try installing the DejaVu fonts (dejavu-fonts.org), which are freely available and then select that font in the Erlang shell application.</p>
-<p>On Unix&reg;-like operating systems, the terminal should be able to handle UTF-8 on input and output (modern versions of XTerm, KDE konsole and the Gnome terminal do for example) and your locale settings have to be proper. As an example, my LANG environment variable is set as this:</p>
+<p>On Windows&reg;, proper operation requires that a suitable font is installed and selected for the Erlang application to use. If no suitable font is available on your system, try installing the DejaVu fonts (<c>dejavu-fonts.org</c>), which are freely available and then select that font in the Erlang shell application.</p>
+<p>On Unix&reg;-like operating systems, the terminal should be able to handle UTF-8 on input and output (modern versions of XTerm, KDE konsole and the Gnome terminal do for example) and your locale settings have to be proper. As an example, my <c>LANG</c> environment variable is set as this:</p>
<pre>
$ <input>echo $LANG</input>
en_US.UTF-8</pre>
-<p>Actually, most systems handle the LC_CTYPE variable before LANG, so if that is set, it has to be set to UTF-8:</p>
+<p>Actually, most systems handle the <c>LC_CTYPE</c> variable before <c>LANG</c>, so if that is set, it has to be set to <c>UTF-8</c>:</p>
<pre>
$ echo <input>$LC_CTYPE</input>
en_US.UTF-8</pre>
-<p>The LANG or LC_CTYPE setting should be consistent with what the terminal is capable of, there is no portable way for Erlang to ask the actual terminal about its UTF-8 capacity, we have to rely on the language and character type settings.</p>
+<p>The <c>LANG</c> or <c>LC_CTYPE</c> setting should be consistent with what the terminal is capable of, there is no portable way for Erlang to ask the actual terminal about its UTF-8 capacity, we have to rely on the language and character type settings.</p>
<p>To investigate what Erlang thinks about the terminal, the <c>io:getopts()</c> call can be used when the shell is started:</p>
<pre>
$ <input>LC_CTYPE=en_US.ISO-8859-1 erl</input>
-Erlang R13A (erts-5.7) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
+Erlang R16B (erts-5.10) [source] [async-threads:0] [hipe] [kernel-poll:false]
-Eshell V5.7 (abort with ^G)
-1> <input>lists:keyfind(encoding,1,io:getopts()).</input>
+Eshell V5.10 (abort with ^G)
+1> <input>lists:keyfind(encoding, 1, io:getopts()).</input>
{encoding,latin1}
2> <input>q().</input>
ok
$ <input>LC_CTYPE=en_US.UTF-8 erl</input>
-Erlang R13A (erts-5.7) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
+Erlang R16B (erts-5.10) [source] [async-threads:0] [hipe] [kernel-poll:false]
-Eshell V5.7 (abort with ^G)
-1> <input>lists:keyfind(encoding,1,io:getopts()).</input>
+Eshell V5.10 (abort with ^G)
+1> <input>lists:keyfind(encoding, 1, io:getopts()).</input>
{encoding,unicode}
2></pre>
<p>When (finally?) everything is in order with the locale settings, fonts and the terminal emulator, you probably also have discovered a way to input characters in the script you desire. For testing, the simplest way is to add some keyboard mappings for other languages, usually done with some applet in your desktop environment. In my KDE environment, I start the KDE Control Center (Personal Settings), select "Regional and Accessibility" and then "Keyboard Layout". On Windows XP&reg;, I start Control Panel->Regional and Language Options, select the Language tab and click the Details... button in the square named "Text services and input Languages". Your environment probably provides similar means of changing the keyboard layout. Make sure you have a way to easily switch back and forth between keyboards if you are not used to this, entering commands using a Cyrillic character set is, as an example, not easily done in the Erlang shell.</p>
<p>Now you are set up for some Unicode input and output. The simplest thing to do is of course to enter a string in the shell:</p>
-<image file="ushell1.gif"><icaption>Cyrillic characters in an Erlang shell</icaption></image>
+<pre>
+$ <input>erl</input>
+Erlang R16B (erts-5.10) [source] [async-threads:0] [hipe] [kernel-poll:false]
+
+Eshell V5.10 (abort with ^G)
+1> <input>lists:keyfind(encoding, 1, io:getopts()).</input>
+{encoding,unicode}
+2> <input>"уницоде"</input>
+"уницоде"
+3> <input>io:format("~ts~n", [v(2)]).</input>
+уницоде
+ok
+4> </pre>
<p>While strings can be input as Unicode characters, the language elements are still limited to the ISO-latin-1 character set. Only character constants and strings are allowed to be beyond that range:</p>
-<image file="ushell2.gif"><icaption>Unicode characters in allowed and disallowed context</icaption></image>
+<pre>
+$ <input>erl</input>
+Erlang R16B (erts-5.10) [source] [async-threads:0] [hipe] [kernel-poll:false]
+
+Eshell V5.10 (abort with ^G)
+1> <input>$ξ</input>
+958
+2> <input>уницоде.</input>
+* 1: illegal character
+2> </pre>
</section>
<section>
-<title>Unicode file names</title>
+<title>Unicode File Names</title>
<p>Most modern operating systems support Unicode file names in some way or another. There are several different ways to do this and Erlang by default treats the different approaches differently:</p>
<taglist>
<tag>Mandatory Unicode file naming</tag>
@@ -183,7 +197,7 @@ Eshell V5.7 (abort with ^G)
<p>A raw file name is not a list, but a binary. Many non core applications still do not handle file names given as binaries, why such raw names are avoided by default. This means that systems having implemented Unicode file naming through transparent file systems and an UTF-8 convention, do not by default have Unicode file naming turned on. Explicitly turning Unicode file name handling on for these types of systems is considered experimental.</p>
</item>
</taglist>
-<p>The Unicode file naming support was introduced with OTP release R14B01. A VM operating in Unicode file mode can work with files having names in any language or character set (as long as it's supported by the underlying OS and file system). The Unicode character list is used to denote file or directory names and if the file system content is listed, you will also be able to get Unicode lists as return value. The support lies in the kernel and stdlib modules, why most applications (that does not explicitly require the file names to be in the ISO-latin-1 range) will benefit from the Unicode support without change.</p>
+<p>The Unicode file naming support was introduced with OTP release R14B01. A VM operating in Unicode file mode can work with files having names in any language or character set (as long as it is supported by the underlying OS and file system). The Unicode character list is used to denote file or directory names and if the file system content is listed, you will also be able to get Unicode lists as return value. The support lies in the Kernel and STDLIB modules, why most applications (that does not explicitly require the file names to be in the ISO-latin-1 range) will benefit from the Unicode support without change.</p>
<p>On Operating systems with mandatory Unicode file names, this means that you more easily conform to the file names of other (non Erlang) applications, and you can also process file names that, at least on Windows, were completely inaccessible (due to having names that could not be represented in ISO-latin-1). Also you will avoid creating incomprehensible file names on MacOSX as the vfs layer of the OS will accept all your file names as UTF-8 and will not rewrite them.</p>
@@ -193,31 +207,32 @@ Eshell V5.7 (abort with ^G)
<p>It is worth noting that the file <c>encoding</c> options given when opening a file has nothing to do with the file <em>name</em> encoding convention. You can very well open files containing UTF-8 but having file names in ISO-latin-1 or vice versa.</p>
-<note>Erlang drivers and NIF shared objects still can not be named with names containing codepoints beyond 127. This is a known limitation to be removed in a future release. Erlang modules however can, but it is definitely not a good idea and is still considered experimental.</note>
+<note><p>Erlang drivers and NIF shared objects still can not be named with names containing codepoints beyond 127. This is a known limitation to be removed in a future release. Erlang modules however can, but it is definitely not a good idea and is still considered experimental.</p></note>
<section>
-<title>Notes about raw file names and automatic file name conversion</title>
-<p>Raw file names is introduced together with Unicode file name support in erts-5.8.2 (OTP R14B01). The reason &quot;raw file names&quot; is introduced in the system is to be able to consistently represent file names given in different encodings on the same system. Having the VM automatically translate a file name that is not in UTF-8 to a list of Unicode characters might seem practical, but this would open up for both duplicate file names and other inconsistent behavior. Consider a directory containing a file named &quot;bj�rn&quot; in ISO-latin-1, while the Erlang VM is operating in Unicode file name mode (and therefore expecting UTF-8 file naming). The ISO-latin-1 name is not valid UTF-8 and one could be tempted to think that automatic conversion in for example <c>file:list_dir/1</c> is a good idea. But what would happen if we later tried to open the file and have the name as a Unicode list (magically converted from the ISO-latin-1 file name)? The VM will convert the file name given to UTF-8, as this is the encoding expected. Effectively this means trying to open the file named &lt;&lt;&quot;bj�rn&quot;/utf8&gt;&gt;. This file does not exist, and even if it existed it would not be the same file as the one that was listed. We could even create two files named &quot;bj�rn&quot;, one named in the UTF-8 encoding and one not. If <c>file:list_dir/1</c> would automatically convert the ISO-latin-1 file name to a list, we would get two identical file names as the result. To avoid this, we need to differentiate between file names being properly encoded according to the Unicode file naming convention (i.e. UTF-8) and file names being invalid under the encoding. This is done by representing invalid encoding as &quot;raw&quot; file names, i.e. as binaries.</p>
-<p>The core system of Erlang (kernel and stdlib) accepts raw file names except for loadable drivers and executables invoked using <c>open_port({spawn, ...} ...)</c>. <c>open_port({spawn_executable, ...} ...)</c> however does accept them. As mentioned earlier, the arguments given in the option list to <c>open_port({spawn_executable, ...} ...)</c> undergo the same conversion as the file names, meaning that the executable will be provided with arguments in UTF-8 as well. This translation is avoided consistently with how the file names are treated, by giving the argument as a binary.</p>
+<title>Notes About Raw File Names and Automatic File Name Conversion</title>
+
+<p>Raw file names is introduced together with Unicode file name support in erts-5.8.2 (OTP R14B01). The reason &quot;raw file names&quot; is introduced in the system is to be able to consistently represent file names given in different encodings on the same system. Having the VM automatically translate a file name that is not in UTF-8 to a list of Unicode characters might seem practical, but this would open up for both duplicate file names and other inconsistent behavior. Consider a directory containing a file named &quot;björn&quot; in ISO-latin-1, while the Erlang VM is operating in Unicode file name mode (and therefore expecting UTF-8 file naming). The ISO-latin-1 name is not valid UTF-8 and one could be tempted to think that automatic conversion in for example <c>file:list_dir/1</c> is a good idea. But what would happen if we later tried to open the file and have the name as a Unicode list (magically converted from the ISO-latin-1 file name)? The VM will convert the file name given to UTF-8, as this is the encoding expected. Effectively this means trying to open the file named &lt;&lt;&quot;björn&quot;/utf8&gt;&gt;. This file does not exist, and even if it existed it would not be the same file as the one that was listed. We could even create two files named &quot;björn&quot;, one named in the UTF-8 encoding and one not. If <c>file:list_dir/1</c> would automatically convert the ISO-latin-1 file name to a list, we would get two identical file names as the result. To avoid this, we need to differentiate between file names being properly encoded according to the Unicode file naming convention (i.e. UTF-8) and file names being invalid under the encoding. This is done by representing invalid encoding as &quot;raw&quot; file names, i.e. as binaries.</p>
+<p>The core system of Erlang (Kernel and STDLIB) accepts raw file names except for loadable drivers and executables invoked using <c>open_port({spawn, ...} ...)</c>. <c>open_port({spawn_executable, ...} ...)</c> however does accept them. As mentioned earlier, the arguments given in the option list to <c>open_port({spawn_executable, ...} ...)</c> undergo the same conversion as the file names, meaning that the executable will be provided with arguments in UTF-8 as well. This translation is avoided consistently with how the file names are treated, by giving the argument as a binary.</p>
<p>To force Unicode file name translation mode on systems where this is not the default is considered experimental in OTP R14B01 due to the raw file names possibly being a new experience to the programmer and that the non core applications of OTP are not tested for compliance with raw file names yet. Unicode file name translation is expected to be default in future releases.</p>
-<p>If working with raw file names, one can still conform to the encoding convention of the Erlang VM by using the <c>file:native_name_encoding/0</c> function, which returns either the atom <c>latin1</c> or the atom <c>utf8</c> depending on the file name translation mode. On Linux, a VM started without explicitly stating the file name translation mode will default to <c>latin1</c> as the native file name encoding, why file names on the disk encoded as UTF-8 will be returned as a list of the names interpreted as ISO-latin-1. The &quot;UTF-8 list&quot; is not a practical type for displaying or operating on in Erlang, but it is backward compatible and usable in all functions requiring a file name. On Windows and MacOSX, the default behavior is that of file name translation, why the <c>file:native_name_encoding/0</c> by default returns <c>utf8</c> on those systems (the fact that Windows actually does not use UTF-8 on the file system level can safely be ignored by the Erlang programmer). The default behavior can be changed using the <c>+fnu</c> or <c>+fnl</c> options to the VM, see the <c>erl</c> command manual page.</p>
+<p>If working with raw file names, one can still conform to the encoding convention of the Erlang VM by using the <c>file:native_name_encoding/0</c> function, which returns either the atom <c>latin1</c> or the atom <c>utf8</c> depending on the file name translation mode. On Linux, a VM started without explicitly stating the file name translation mode will default to <c>latin1</c> as the native file name encoding, why file names on the disk encoded as UTF-8 will be returned as a list of the names interpreted as ISO-latin-1. The &quot;UTF-8 list&quot; is not a practical type for displaying or operating on in Erlang, but it is backward compatible and usable in all functions requiring a file name. On Windows and MacOSX, the default behavior is that of file name translation, why the <c>file:native_name_encoding/0</c> by default returns <c>utf8</c> on those systems (the fact that Windows actually does not use UTF-8 on the file system level can safely be ignored by the Erlang programmer). The default behavior can be changed using the <c>+fnu</c> or <c>+fnl</c> options to the VM, see the <seealso marker="erts:erl"><c>erl(1)</c></seealso> command manual page.</p>
<p>Even if you are operating without Unicode file naming translation automatically done by the VM, you can access and create files with names in UTF-8 encoding by using raw file names encoded as UTF-8. Enforcing the UTF-8 encoding regardless of the mode the Erlang VM is started in might, in some circumstances be a good idea, as the convention of using UTF-8 file names is spreading.</p>
</section>
<section>
-<title>Notes about MacOSX</title>
+<title>Notes About MacOSX</title>
<p>MacOSXs vfs layer enforces UTF-8 file names in a quite aggressive way. Older versions did this by simply refusing to create non UTF-8 conforming file names, while newer versions replace offending bytes with the sequence &quot;%HH&quot;, where HH is the original character in hexadecimal notation. As Unicode translation is enabled by default on MacOSX, the only way to come up against this is to either start the VM with the <c>+fnl</c> flag or to use a raw file name in <c>latin1</c> encoding. In that case, the file can not be opened with the same name as the one used to create this. The problem is by design in newer versions of MacOSX.</p>
-<p>MacOSX also reorganizes the names of files so that the representation of accents etc is denormalized, i.e. the character <c>�</c> is represented as the codepoints [111,776], where 111 is the character <c>o</c> and 776 is a special accent character. This type of denormalized Unicode is otherwise very seldom used and Erlang normalizes those file names on retrieval, so that denormalized file names is not passed up to the Erlang application. In Erlang the file name &quot;bj�rn&quot; is retrieved as [98,106,246,114,110], not as [98,106,117,776,114,110], even though the file system might think differently.</p>
+<p>MacOSX also reorganizes the names of files so that the representation of accents etc is denormalized, i.e. the character <c>ö</c> is represented as the codepoints [111,776], where 111 is the character <c>o</c> and 776 is a special accent character. This type of denormalized Unicode is otherwise very seldom used and Erlang normalizes those file names on retrieval, so that denormalized file names is not passed up to the Erlang application. In Erlang the file name &quot;björn&quot; is retrieved as [98,106,246,114,110], not as [98,106,117,776,114,110], even though the file system might think differently.</p>
</section>
</section>
<section>
-<title>Unicode in environment variables and parameters</title>
+<title>Unicode in Environment Variables and Parameters</title>
<p>Environment variables and their interpretation is handled much in the same way as file names. If Unicode file names are enabled, environment variables as well as parameters to the Erlang VM are expected to be in Unicode.</p>
<p>If Unicode file names are enabled, the calls to <seealso marker="kernel:os#getenv/0"><c>os:getenv/0</c></seealso>, <seealso marker="kernel:os#getenv/1"><c>os:getenv/1</c></seealso> and <seealso marker="kernel:os#putenv/2"><c>os:putenv/2</c></seealso> will handle Unicode strings. On Unix-like platforms, the built-in functions will translate environment variables in UTF-8 to/from Unicode strings, possibly with codepoints > 255. On Windows the Unicode versions of the environment system API will be used, also allowing for codepoints > 255.</p>
<p>On Unix-like operating systems, parameters are expected to be UTF-8 without translation if Unicode file names are enabled.</p>
</section>
<section>
-<title>Unicode-aware modules</title>
-<p>Most of the modules in Erlang/OTP are of course Unicode-unaware in the sense that they have no notion of Unicode and really shouldn't have. Typically they handle non-textual or byte-oriented data (like <c>gen_tcp</c> etc).</p>
+<title>Unicode-aware Modules</title>
+<p>Most of the modules in Erlang/OTP are of course Unicode-unaware in the sense that they have no notion of Unicode and really should not have. Typically they handle non-textual or byte-oriented data (like <c>gen_tcp</c> etc).</p>
<p>Modules that actually handle textual data (like <c>io_lib</c>, <c>string</c> etc) are sometimes subject to conversion or extension to be able to handle Unicode characters.</p>
<p>Fortunately, most textual data has been stored in lists and range checking has been sparse, why modules like <c>string</c> works well for Unicode lists with little need for conversion or extension.</p>
<p>Some modules are however changed to be explicitly Unicode-aware. These modules include:</p>
@@ -230,7 +245,7 @@ Eshell V5.7 (abort with ^G)
<item>
<p>The <seealso marker="stdlib:io">io</seealso> module has been extended along with the actual I/O-protocol to handle Unicode data. This means that several functions require binaries to be in UTF-8 and there are modifiers to formatting control sequences to allow for outputting of Unicode strings.</p>
</item>
-<tag><c>file</c>, <c>group</c> and <c>user</c></tag>
+<tag><c>file</c>, <c>group</c>, <c>user</c></tag>
<item>
<p>I/O-servers throughout the system are able both to handle Unicode data and has options for converting data upon actual output or input to/from the device. As shown earlier, the <seealso marker="stdlib:shell">shell</seealso> has support for Unicode terminals and the <seealso marker="kernel:file">file</seealso> module allows for translation to and from various Unicode formats on disk.</p>
<p>The actual reading and writing of files with Unicode data is however not best done with the <c>file</c> module as its interface is byte oriented. A file opened with a Unicode encoding (like UTF-8), is then best read or written using the <seealso marker="stdlib:io">io</seealso> module.</p>
@@ -247,10 +262,10 @@ Eshell V5.7 (abort with ^G)
<p>The module <seealso marker="stdlib:string">string</seealso> works perfect for Unicode strings as well as for ISO-latin-1 strings with the exception of the language-dependent <seealso marker="stdlib:string#to_upper/1">to_upper</seealso> and <seealso marker="stdlib:string#to_lower/1">to_lower</seealso> functions, which are only correct for the ISO-latin-1 character set. Actually they can never function correctly for Unicode characters in their current form, there are language and locale issues as well as multi-character mappings to consider when conversion text between cases. Converting case in an international environment is a big subject not yet addressed in OTP.</p>
</section>
<section>
-<title>Unicode recipes</title>
+<title>Unicode Recipes</title>
<p>When starting with Unicode, one often stumbles over some common issues. I try to outline some methods of dealing with Unicode data in this section.</p>
<section>
-<title>Byte order marks</title>
+<title>Byte Order Marks</title>
<p>A common method of identifying encoding in text-files is to put a byte order mark (BOM) first in the file. The BOM is the codepoint 16#FEFF encoded in the same way as the rest of the file. If such a file is to be read, the first few bytes (depending on encoding) is not part of the actual text. This code outlines how to open a file which is believed to have a BOM and set the files encoding and position for further sequential reading (preferably using the <seealso marker="stdlib:io">io</seealso> module). Note that error handling is omitted from the code:</p>
<code>
open_bom_file_for_reading(File) -&gt;
@@ -261,7 +276,7 @@ open_bom_file_for_reading(File) -&gt;
io:setopts(F,[{encoding,Type}]),
{ok,F}.
</code>
-<p>The <c>unicode:bom_to_encoding/1</c> function identifies the encoding from a binary of at least four bytes. It returns, along with an term suitable for setting the encoding of the file, the actual length of the BOM, so that the file position can be set accordingly. Note that <c>file:position</c> always works on byte-offsets, so that the actual byte-length of the BOM is needed.</p>
+<p>The <c>unicode:bom_to_encoding/1</c> function identifies the encoding from a binary of at least four bytes. It returns, along with an term suitable for setting the encoding of the file, the actual length of the BOM, so that the file position can be set accordingly. Note that <c>file:position/2</c> always works on byte-offsets, so that the actual byte-length of the BOM is needed.</p>
<p>To open a file for writing and putting the BOM first is even simpler:</p>
<code>
open_bom_file_for_writing(File,Encoding) -&gt;
@@ -273,24 +288,33 @@ open_bom_file_for_writing(File,Encoding) -&gt;
<p>In both cases the file is then best processed using the <c>io</c> module, as the functions in <c>io</c> can handle codepoints beyond the ISO-latin-1 range.</p>
</section>
<section>
-<title>Formatted input and output</title>
-<p>When reading and writing to Unicode-aware entities, like the User or a file opened for Unicode translation, you will probably want to format text strings using the functions in <seealso marker="stdlib:io">io</seealso> or <seealso marker="stdlib:io_lib">io_lib</seealso>. For backward compatibility reasons, these functions don't accept just any list as a string, but require e special "translation modifier" when working with Unicode texts. The modifier is "t". When applied to the "s" control character in a formatting string, it accepts all Unicode codepoints and expect binaries to be in UTF-8:</p>
+<title>Formatted Input and Output</title>
+<p>When reading and writing to Unicode-aware entities, like the User or a file opened for Unicode translation, you will probably want to format text strings using the functions in <seealso marker="stdlib:io">io</seealso> or <seealso marker="stdlib:io_lib">io_lib</seealso>. For backward compatibility reasons, these functions do not accept just any list as a string, but require a special <em>translation modifier</em> when working with Unicode texts. The modifier is <c>t</c>. When applied to the <c>s</c> control character in a formatting string, it accepts all Unicode codepoints and expect binaries to be in UTF-8:</p>
<pre>
-1> <input>io:format("~ts~n",[&lt;&lt;"���"/utf8&gt;&gt;]).</input>
-���
-ok
-2> <input>io:format("~s~n",[&lt;&lt;"���"/utf8&gt;&gt;]).</input>
+1> <input>io:format("~ts~n",[&lt;&lt;"åäö"/utf8&gt;&gt;]).</input>
åäö
+ok
+2> <input>io:format("~s~n",[&lt;&lt;"åäö"/utf8&gt;&gt;]).</input>
+åäö
+ok</pre>
+<p>Obviously the second <c>io:format/2</c> gives undesired output because the UTF-8 binary is not in latin1. Because ISO-latin-1 is still the defined character set of Erlang, the non prefixed <c>s</c> control character expects ISO-latin-1 in binaries as well as lists.</p>
+<p>As long as the data is always lists, the <c>t</c> modifier can be used for any string, but when binary data is involved, care must be taken to make the right choice of formatting characters.</p>
+<p>The function <c>format/2</c> in <c>io_lib</c> behaves similarly. This function is defined to return a deep list of characters and the output could easily be converted to binary data for outputting on a device of any kind by a simple <c>erlang:list_to_binary/1</c>. When the translation modifier is used, the list can however contain characters that cannot be stored in one byte. The call to <c>erlang:list_to_binary/1</c> will in that case fail. However, if the I/O server you want to communicate with is Unicode-aware, the list returned can still be used directly:</p>
+<pre>
+$ <input>erl</input>
+Erlang R16B (erts-5.10) [source] [async-threads:0] [hipe] [kernel-poll:false]
+
+Eshell V5.10 (abort with ^G)
+1> <input>io_lib:format("~ts~n", ["θνιψοδε"]).</input>
+["θνιψοδε","\n"]
+2> <input>io:put_chars(io_lib:format("~ts~n", ["θνιψοδε"])).</input>
+θνιψοδε
ok</pre>
-<p>Obviously the second <c>io:format</c> gives undesired output because the UTF-8 binary is not in latin1. Because ISO-latin-1 is still the defined character set of Erlang, the non prefixed "s" control character expects ISO-latin-1 in binaries as well as lists.</p>
-<p>As long as the data is always lists, the "t" modifier can be used for any string, but when binary data is involved, care must be taken to make the tight choice of formatting characters.</p>
-<p>The function <c>format</c> in <c>io_lib</c> behaves similarly. This function is defined to return a deep list of characters and the output could easily be converted to binary data for outputting on a device of any kind by a simple <c>erlang:list_to_binary</c>. When the translation modifier is used, the list can however contain characters that cannot be stored in one byte. The call to <c>erlang:list_to_binary</c> will in that case fail. However, if the io_server you want to communicate with is Unicode-aware, the list returned can still be used directly:</p>
-<image file="ushell3.gif"><icaption>io_lib:format with Unicode translation</icaption></image>
-<p>The Unicode string is returned as a Unicode list, why the return value of <c>io_lib:format</c> no longer qualifies as a regular Erlang string (the function <seealso marker="stdlib:io_lib#deep_char_list/1">io_lib:deep_char_list</seealso> will, as an example, return <c>false</c>). The Unicode list is however valid input to the <seealso marker="stdlib:io#put_chars/2">io:put_chars</seealso> function, so data can be output on any Unicode capable device anyway. If the device is a terminal, characters will be output in the \x{H ...} format if encoding is <c>latin1</c> otherwise in UTF-8 (for the non-interactive terminal - "oldshell" or "noshell") or whatever is suitable to show the character properly (for an interactive terminal - the regular shell). The bottom line is that you can always send Unicode data to the <c>standard_io</c> device. Files will however only accept Unicode codepoints beyond ISO-latin-1 if <c>encoding</c> is set to something else than <c>latin1</c>.</p>
+<p>The Unicode string is returned as a Unicode list, which is recognized as such since the Erlang shell uses the Unicode encoding. The Unicode list is valid input to the <seealso marker="stdlib:io#put_chars/2">io:put_chars/2</seealso> function, so data can be output on any Unicode capable device. If the device is a terminal, characters will be output in the <c>\x{</c>H ...<c>}</c> format if encoding is <c>latin1</c> otherwise in UTF-8 (for the non-interactive terminal - "oldshell" or "noshell") or whatever is suitable to show the character properly (for an interactive terminal - the regular shell). The bottom line is that you can always send Unicode data to the <c>standard_io</c> device. Files will however only accept Unicode codepoints beyond ISO-latin-1 if <c>encoding</c> is set to something else than <c>latin1</c>.</p>
</section>
<section>
-<title>Heuristic identification of UTF-8</title>
-<p>While it's strongly encouraged that the actual encoding of characters in binary data is known prior to processing, that is not always possible. On a typical Linux&reg; system, there is a mix of UTF-8 and ISO-latin-1 text files and there are seldom any BOM's in the files to identify them.</p>
+<title>Heuristic Identification of UTF-8</title>
+<p>While it iss strongly encouraged that the actual encoding of characters in binary data is known prior to processing, that is not always possible. On a typical Linux&reg; system, there is a mix of UTF-8 and ISO-latin-1 text files and there are seldom any BOM's in the files to identify them.</p>
<p>UTF-8 is designed in such a way that ISO-latin-1 characters with numbers beyond the 7-bit ASCII range are seldom considered valid when decoded as UTF-8. Therefore one can usually use heuristics to determine if a file is in UTF-8 or if it is encoded in ISO-latin-1 (one byte per character) encoding. The <c>unicode</c> module can be used to determine if data can be interpreted as UTF-8:</p>
<code>
heuristic_encoding_bin(Bin) when is_binary(Bin) -&gt;
diff --git a/lib/stdlib/doc/src/ushell1.gif b/lib/stdlib/doc/src/ushell1.gif
deleted file mode 100644
index 7c46464fd2..0000000000
--- a/lib/stdlib/doc/src/ushell1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/stdlib/doc/src/ushell1.ps b/lib/stdlib/doc/src/ushell1.ps
deleted file mode 100644
index 95bfebf194..0000000000
--- a/lib/stdlib/doc/src/ushell1.ps
+++ /dev/null
@@ -1,1196 +0,0 @@
-%!PS-Adobe-3.0
-%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner
-%%Title: ushell1.ps
-%%CreationDate: Mon Mar 16 09:53:27 2009
-%%DocumentData: Clean7Bit
-%%LanguageLevel: 2
-%%Pages: 1
-%%BoundingBox: 14 14 468 142
-%%EndComments
-%%BeginProlog
-% Use own dictionary to avoid conflicts
-10 dict begin
-%%EndProlog
-%%Page: 1 1
-% Translate for offset
-14.173228346456694 14.173228346456694 translate
-% Translate to begin of first scanline
-0 127.55905511811024 translate
-453.54330708661422 -127.55905511811024 scale
-% Image geometry
-640 180 8
-% Transformation matrix
-[ 640 0 0 180 0 0 ]
-% Strings to hold RGB-samples per scanline
-/rstr 640 string def
-/gstr 640 string def
-/bstr 640 string def
-{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
-{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
-{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
-true 3
-%%BeginData: 67571 ASCII Bytes
-colorimage
-JP1PeJP1PeJP1L~>
-JP1PeJP1PeJP1L~>
-JP1PeJP1PeJP1L~>
-!!e'9JNA?CJNABDJ,~>
-!!e'9JNA?CJNABDJ,~>
-!!e'9JNA?CJNABDJ,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$2%<!Lr-2rr]6=Dt\b^JcC<$JcD\KJ,~>
-!$2%<!Lr-2rr]6=Dt\b^JcC<$JcD\KJ,~>
-!$2%<!Lr-2rr]6=Dt\b^JcC<$JcD\KJ,~>
-#9EjEY>Q6)=6BMbc`J;XJcC<$JcC<$W;hA~>
-#9EjEY>Q6)=6BMbc`J;XJcC<$JcC<$W;hA~>
-#9EjEY>Q6)=6BMbc`J;XJcC<$JcC<$W;hA~>
-#T`rUH-/@H`Dbmu!A3bks+13$s+13Ks*t~>
-#T`rUH-/@H`Dbmu!A3bks+13$s+13Ks*t~>
-#T`rUH-/@H`Dbmu!A3bks+13$s+13Ks*t~>
-#T`rEG5Y4]rp0@Z!W@cP*=4P!s-oDP9H?1krVlmMmt(Lis+13$s/>sJ~>
-#T`rEG5Y4]rp0@Z!W@cP*=4P!s-oDP9H?1krVlmMmt(Lis+13$s/>sJ~>
-#T`rEG5Y4]rp0@Z!W@cP*=4P!s-oDP9H?1krVlmMmt(Lis+13$s/>sJ~>
-#9EjER>jY@r:g3lQA5D=$0F2Hs)Ak%s4op<rrF_?JcC<$JcC<$W;hA~>
-#9EjER>jY@r:g3lQA5D=$0F2Hs)Ak%s4op<rrF_?JcC<$JcC<$W;hA~>
-#9EjER>jY@r:g3lQA5D=$0F2Hs)Ak%s4op<rrF_?JcC<$JcC<$W;hA~>
-!$2(="-F9Q\G-"(Q=^'2$*?/ds)G.?s5e.srrF_?JcC<$JcC<$W;hA~>
-!$2(="-F9Q\G-"(Q=^'2$*?/ds)G.?s5e.srrF_?JcC<$JcC<$W;hA~>
-!$2(="-F9Q\G-"(Q=^'2$*?/ds)G.?s5e.srrF_?JcC<$JcC<$W;hA~>
-!$2%<"&I0WZ2">"Q8&8B"FpIOENK!9!A3bks+13$s+13Ks*t~>
-!$2%<"&I0WZ2">"Q8&8B"FpIOENK!9!A3bks+13$s+13Ks*t~>
-!$2%<"&I0WZ2">"Q8&8B"FpIOENK!9!A3bks+13$s+13Ks*t~>
-#T`rq^Ah!RpEo\8!LAK:rrI,@q>UIImt(Lis+13$s/>sJ~>
-#T`rq^Ah!RpEo\8!LAK:rrI,@q>UIImt(Lis+13$s/>sJ~>
-#T`rq^Ah!RpEo\8!LAK:rrI,@q>UIImt(Lis+13$s/>sJ~>
-#T`s"JSH?.CSgh+!RuStC&iMXrrI,@qu6esC(k*/JcC<$JcC<$WW.J~>
-#T`s"JSH?.CSgh+!RuStC&iMXrrI,@qu6esC(k*/JcC<$JcC<$WW.J~>
-#T`s"JSH?.CSgh+!RuStC&iMXrrI,@qu6esC(k*/JcC<$JcC<$WW.J~>
-#9EjEgp/o#[J'V#fD`&U])M^1eE6Z.!7LkP!5F*bJcC<$JcD_LJ,~>
-#9EjEgp/o#[J'V#fD`&U])M^1eE6Z.!7LkP!5F*bJcC<$JcD_LJ,~>
-#9EjEgp/o#[J'V#fD`&U])M^1eE6Z.!7LkP!5F*bJcC<$JcD_LJ,~>
-!$2%<!T*O$s+13$s+13+s*t~>
-!$2%<!T*O$s+13$s+13+s*t~>
-!$2%<!T*O$s+13$s+13+s*t~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$.X1!VbZgrrMcToD\g]rn%5Fci4"4rn%5Kp&>-Vf\#!)rr_95f\lE%"5DJ\kK!T&r;P=KmIgJZ
-p&<SDo\]ZKoD[ABp@\Fcm/GW;rJ1CTgXt0Ap&>$hrn%5=kPp&~>
-!$.X1!VbZgrrMcToD\g]rn%5Fci4"4rn%5Kp&>-Vf\#!)rr_95f\lE%"5DJ\kK!T&r;P=KmIgJZ
-p&<SDo\]ZKoD[ABp@\Fcm/GW;rJ1CTgXt0Ap&>$hrn%5=kPp&~>
-!$.X1!VbZgrrMcToD\g]rn%5Fci4"4rn%5Kp&>-Vf\#!)rr_95f\lE%"5DJ\kK!T&r;P=KmIgJZ
-p&<SDo\]ZKoD[ABp@\Fcm/GW;rJ1CTgXt0Ap&>$hrn%5=kPp&~>
-!Zh=)r4;sJp\t?M]=[dnrrC^M])^+RrrBt8rrCOG])^O`rrN,;oD\mfUOUkp!5JHD!:K[_!<2l-
-"nM]nb];P3rrf;C6q#_Srrf>i6k8JSrrZO_6rs9d"4Ffn`;BQ8r5SL2!SZc5rrL6To`##66p3I#
-rrWs'7#p%%s5ESL#i+SBs6i?D-]@Zt"M5R?7*O]k#gN&Bs2.5m(WQ.J"Fqsi7/+e&!SceorrM<;
-mf3=!!7LiG"&[email protected])jpjdIXT/=<lMlA~>
-!Zh=)r4;sJp\t?M]=[dnrrC^M])^+RrrBt8rrCOG])^O`rrN,;oD\mfUOUkp!5JHD!:K[_!<2l-
-"nM]nb];P3rrf;C6q#_Srrf>i6k8JSrrZO_6rs9d"4Ffn`;BQ8r5SL2!SZc5rrL6To`##66p3I#
-rrWs'7#p%%s5ESL#i+SBs6i?D-]@Zt"M5R?7*O]k#gN&Bs2.5m(WQ.J"Fqsi7/+e&!SceorrM<;
-mf3=!!7LiG"&[email protected])jpjdIXT/=<lMlA~>
-!Zh=)r4;sJp\t?M]=[dnrrC^M])^+RrrBt8rrCOG])^O`rrN,;oD\mfUOUkp!5JHD!:K[_!<2l-
-"nM]nb];P3rrf;C6q#_Srrf>i6k8JSrrZO_6rs9d"4Ffn`;BQ8r5SL2!SZc5rrL6To`##66p3I#
-rrWs'7#p%%s5ESL#i+SBs6i?D-]@Zt"M5R?7*O]k#gN&Bs2.5m(WQ.J"Fqsi7/+e&!SceorrM<;
-mf3=!!7LiG"&[email protected])jpjdIXT/=<lMlA~>
-"!.E>/H&uWGk_4?XC2t&hZ!Um6iLKpEPqeU!Nm==rrAJc@0&Z7rr3%sBt![6!U2E,rrMo!m/I&"
-r*]TWq>UHor*]UHci3qFSUgA4!NC.^rrFq?p&>%u_#438a`V$#Fo21>SLO=5!Hk=9rrIX^qu6]"
-qYL3mju2l3!$0bm!oI+@o`#!G9q_Fa!Ki<5rrK`?iVrtr.,4\"!ER55rrIY@bPqUQnGW@fGGa6s
-!Mju/rrf?1@<TfkrrKf@p&>'T2Z3RT*U<ZT~>
-"!.E>/H&uWGk_4?XC2t&hZ!Um6iLKpEPqeU!Nm==rrAJc@0&Z7rr3%sBt![6!U2E,rrMo!m/I&"
-r*]TWq>UHor*]UHci3qFSUgA4!NC.^rrFq?p&>%u_#438a`V$#Fo21>SLO=5!Hk=9rrIX^qu6]"
-qYL3mju2l3!$0bm!oI+@o`#!G9q_Fa!Ki<5rrK`?iVrtr.,4\"!ER55rrIY@bPqUQnGW@fGGa6s
-!Mju/rrf?1@<TfkrrKf@p&>'T2Z3RT*U<ZT~>
-"!.E>/H&uWGk_4?XC2t&hZ!Um6iLKpEPqeU!Nm==rrAJc@0&Z7rr3%sBt![6!U2E,rrMo!m/I&"
-r*]TWq>UHor*]UHci3qFSUgA4!NC.^rrFq?p&>%u_#438a`V$#Fo21>SLO=5!Hk=9rrIX^qu6]"
-qYL3mju2l3!$0bm!oI+@o`#!G9q_Fa!Ki<5rrK`?iVrtr.,4\"!ER55rrIY@bPqUQnGW@fGGa6s
-!Mju/rrf?1@<TfkrrKf@p&>'T2Z3RT*U<ZT~>
-"!.E>Fn#D352P/r!Go">rs$)Ds8SmD(]"(;jFF`>s."Z-J$8PF!JQp-rrML@m/I&+mf*?sJ*6h2
-!mQ8Ap&>&lF34F_1[4T4!F<M>rrU8keG9+GR!:(SrrI8?nc&V>o(r@eju2l3!$0en"6=u%O7iMT
-gjhP\r;Qe[MtR)N]4'_!"297-g\h'P<lXh4!J$`arrGO?rVlnBVV_=RUj2D/#+pAEs3lJ>rVlo3
[email protected]#ju3/;!$1A)J,~>
-"!.E>Fn#D352P/r!Go">rs$)Ds8SmD(]"(;jFF`>s."Z-J$8PF!JQp-rrML@m/I&+mf*?sJ*6h2
-!mQ8Ap&>&lF34F_1[4T4!F<M>rrU8keG9+GR!:(SrrI8?nc&V>o(r@eju2l3!$0en"6=u%O7iMT
-gjhP\r;Qe[MtR)N]4'_!"297-g\h'P<lXh4!J$`arrGO?rVlnBVV_=RUj2D/#+pAEs3lJ>rVlo3
[email protected]#ju3/;!$1A)J,~>
-"!.E>Fn#D352P/r!Go">rs$)Ds8SmD(]"(;jFF`>s."Z-J$8PF!JQp-rrML@m/I&+mf*?sJ*6h2
-!mQ8Ap&>&lF34F_1[4T4!F<M>rrU8keG9+GR!:(SrrI8?nc&V>o(r@eju2l3!$0en"6=u%O7iMT
-gjhP\r;Qe[MtR)N]4'_!"297-g\h'P<lXh4!J$`arrGO?rVlnBVV_=RUj2D/#+pAEs3lJ>rVlo3
[email protected]#ju3/;!$1A)J,~>
-"!.E>Fo21B`NfH(A8hDG!C#B=rrB%tA-dJ\s0]Y*A7U/grro!)A9-Unq#:A2Yl=Y,]4(`5N:.e`
-rsS:7]`8"tO7rV9LTgFO!$1t:!-S9O&?Pp3K(J/9A?l17I9dLsA@MR<!+u4@!5/(+!?L;$A,sX@
-rrHo@r;QeISb<!`WH8";!8%0["6KR_df!\YlMob-rr3C]n,M+2s.s7:o`+s/rF?$+s8Th3A,uW,
-rrFq?p&>%u_#=96O,`u8"-Sf5.JNiGFf1%+A;L6b!gR;1rVm%pA.`0ZP5P=\ju2l3!$1t:!.4]U%
-&a.*Lh(\`A?>h2KC/YK!3uM&!omgerVm#hE4h0krVlrPA?Pn2"QaaBIA$N<!Ki<5rrK`?rVm2rJ
-cEJqAD7(`h>Updc%Y]errTT=df'1K_1:6*g\h'P<lXh4!J$a=rrBe3A-;i2s1/,>"DIi8`ioCA#
-^67J_6fbDA97bM!36$/!-n8<'sV9g<Fg^]s*(>sA7UJqs/40BEb(..rrA/[A,qbkrr@uVA,qqpr
-s4?iA;[1-s8RZLA,r>%rrVe&PlC[`45p2=!K3->rrKf@p&>'T2Z3RT*W?!?Us]5;rF?8Ss8R9Bc
-X^S/s8RT~>
-"!.E>Fo21B`NfH(A8hDG!C#B=rrB%tA-dJ\s0]Y*A7U/grro!)A9-Unq#:A2Yl=Y,]4(`5N:.e`
-rsS:7]`8"tO7rV9LTgFO!$1t:!-S9O&?Pp3K(J/9A?l17I9dLsA@MR<!+u4@!5/(+!?L;$A,sX@
-rrHo@r;QeISb<!`WH8";!8%0["6KR_df!\YlMob-rr3C]n,M+2s.s7:o`+s/rF?$+s8Th3A,uW,
-rrFq?p&>%u_#=96O,`u8"-Sf5.JNiGFf1%+A;L6b!gR;1rVm%pA.`0ZP5P=\ju2l3!$1t:!.4]U%
-&a.*Lh(\`A?>h2KC/YK!3uM&!omgerVm#hE4h0krVlrPA?Pn2"QaaBIA$N<!Ki<5rrK`?rVm2rJ
-cEJqAD7(`h>Updc%Y]errTT=df'1K_1:6*g\h'P<lXh4!J$a=rrBe3A-;i2s1/,>"DIi8`ioCA#
-^67J_6fbDA97bM!36$/!-n8<'sV9g<Fg^]s*(>sA7UJqs/40BEb(..rrA/[A,qbkrr@uVA,qqpr
-s4?iA;[1-s8RZLA,r>%rrVe&PlC[`45p2=!K3->rrKf@p&>'T2Z3RT*W?!?Us]5;rF?8Ss8R9Bc
-X^S/s8RT~>
-"!.E>Fo21B`NfH(A8hDG!C#B=rrB%tA-dJ\s0]Y*A7U/grro!)A9-Unq#:A2Yl=Y,]4(`5N:.e`
-rsS:7]`8"tO7rV9LTgFO!$1t:!-S9O&?Pp3K(J/9A?l17I9dLsA@MR<!+u4@!5/(+!?L;$A,sX@
-rrHo@r;QeISb<!`WH8";!8%0["6KR_df!\YlMob-rr3C]n,M+2s.s7:o`+s/rF?$+s8Th3A,uW,
-rrFq?p&>%u_#=96O,`u8"-Sf5.JNiGFf1%+A;L6b!gR;1rVm%pA.`0ZP5P=\ju2l3!$1t:!.4]U%
-&a.*Lh(\`A?>h2KC/YK!3uM&!omgerVm#hE4h0krVlrPA?Pn2"QaaBIA$N<!Ki<5rrK`?rVm2rJ
-cEJqAD7(`h>Updc%Y]errTT=df'1K_1:6*g\h'P<lXh4!J$a=rrBe3A-;i2s1/,>"DIi8`ioCA#
-^67J_6fbDA97bM!36$/!-n8<'sV9g<Fg^]s*(>sA7UJqs/40BEb(..rrA/[A,qbkrr@uVA,qqpr
-s4?iA;[1-s8RZLA,r>%rrVe&PlC[`45p2=!K3->rrKf@p&>'T2Z3RT*W?!?Us]5;rF?8Ss8R9Bc
-X^S/s8RT~>
-"!.E>+oY"=nGiOLJ4Q':Y\F(9!C#B=rrC[M[h5T^s+Mqh\$r2\s.PF]\#s&_q#:A21B'fKA^g\.
-li/"%rrth%K`D'Nb5VDAU3cP5!$2";!HG1>[hOJ#s2@f;\$pmts21i\\$t2ns'E/5[fL`lq#:@.
->Q2)4ER=CY!i_%@r;QeISb<!`WH8%<!Tdkj[f]k-he;tt"'>BB;Z?\)39C2.O@Y5;[oi[TF8`QM
->5uWerO2c3r;QdRl1P&W?,6F="cnXr84[+erreOOo(+=)rsNs&T!u2#L]@D"[ho#C"k:"&Y.)XQ
-rrM7?o`"n3r;QeBVuF.6Lo^P:UT.b3KX(P47fKjtJ@GOX!mgp]rVm"#a8_-[rVlr7!.+YE"nc'C
-s*^R<rrJ7?p&>')@K$34qP-T)\$ol2lsTh%!c/D1rr3%Q!4Dh+"j;#Cs$>E;rrH0?p&>&CSc&Kf
-iVg4f>lVWdrjN$<@K3$Jrr3BIs8SH4NjlL"D?$enrjMp-F85bQgUAo,\&JCIG;#Mr\"8?Sen[gZ
-\!r?VOdQ-W"IG;Os2k8L%$R(YKV,`_S1]'dI\ZnO!K<iRrrVKd:]C@p45p2=!K3->rrKf@p&>'T
-2Z3R\*WQ/Q8;ZX3=oGf:EmOcj88>WCDUnc;~>
-"!.E>+oY"=nGiOLJ4Q':Y\F(9!C#B=rrC[M[h5T^s+Mqh\$r2\s.PF]\#s&_q#:A21B'fKA^g\.
-li/"%rrth%K`D'Nb5VDAU3cP5!$2";!HG1>[hOJ#s2@f;\$pmts21i\\$t2ns'E/5[fL`lq#:@.
->Q2)4ER=CY!i_%@r;QeISb<!`WH8%<!Tdkj[f]k-he;tt"'>BB;Z?\)39C2.O@Y5;[oi[TF8`QM
->5uWerO2c3r;QdRl1P&W?,6F="cnXr84[+erreOOo(+=)rsNs&T!u2#L]@D"[ho#C"k:"&Y.)XQ
-rrM7?o`"n3r;QeBVuF.6Lo^P:UT.b3KX(P47fKjtJ@GOX!mgp]rVm"#a8_-[rVlr7!.+YE"nc'C
-s*^R<rrJ7?p&>')@K$34qP-T)\$ol2lsTh%!c/D1rr3%Q!4Dh+"j;#Cs$>E;rrH0?p&>&CSc&Kf
-iVg4f>lVWdrjN$<@K3$Jrr3BIs8SH4NjlL"D?$enrjMp-F85bQgUAo,\&JCIG;#Mr\"8?Sen[gZ
-\!r?VOdQ-W"IG;Os2k8L%$R(YKV,`_S1]'dI\ZnO!K<iRrrVKd:]C@p45p2=!K3->rrKf@p&>'T
-2Z3R\*WQ/Q8;ZX3=oGf:EmOcj88>WCDUnc;~>
-"!.E>+oY"=nGiOLJ4Q':Y\F(9!C#B=rrC[M[h5T^s+Mqh\$r2\s.PF]\#s&_q#:A21B'fKA^g\.
-li/"%rrth%K`D'Nb5VDAU3cP5!$2";!HG1>[hOJ#s2@f;\$pmts21i\\$t2ns'E/5[fL`lq#:@.
->Q2)4ER=CY!i_%@r;QeISb<!`WH8%<!Tdkj[f]k-he;tt"'>BB;Z?\)39C2.O@Y5;[oi[TF8`QM
->5uWerO2c3r;QdRl1P&W?,6F="cnXr84[+erreOOo(+=)rsNs&T!u2#L]@D"[ho#C"k:"&Y.)XQ
-rrM7?o`"n3r;QeBVuF.6Lo^P:UT.b3KX(P47fKjtJ@GOX!mgp]rVm"#a8_-[rVlr7!.+YE"nc'C
-s*^R<rrJ7?p&>')@K$34qP-T)\$ol2lsTh%!c/D1rr3%Q!4Dh+"j;#Cs$>E;rrH0?p&>&CSc&Kf
-iVg4f>lVWdrjN$<@K3$Jrr3BIs8SH4NjlL"D?$enrjMp-F85bQgUAo,\&JCIG;#Mr\"8?Sen[gZ
-\!r?VOdQ-W"IG;Os2k8L%$R(YKV,`_S1]'dI\ZnO!K<iRrrVKd:]C@p45p2=!K3->rrKf@p&>'T
-2Z3R\*WQ/Q8;ZX3=oGf:EmOcj88>WCDUnc;~>
-"!.E>@K+aVr;Q`rJHPNDmOnJ<!C#B9rt+!Ns+Ppms8UV?s*^O>s62?6rrm5&e/6]nr;Qa;qYpcM
-e=;Er;p,+>!MXo6rr=);rrG.?rr3F`PlLb'g].;(SH&WV0`:qO+T;<>"6]4S55Zo5_Z/6Crr3"*
-^@hL,Lm7f:!Ip[5rrK*?rVloQ62gfch#5\orVlsEq8uV7rsUmKs8Sm*mJm2,s1)Y<rr^sSZ#'C=
-!$2";!Aj!5rrHE@rVmFi(nB+*^0^i/Nq35A.KBF4r$r%hs)j7ms8U&>rVlj<qu6[Ho(r@eju2l3
-!$2";!CPT?rs\;\s#T/u49(2%s"_RmrrI\?rr3&oeE6c1"\.)Cs,E*<rrViBl2L\d6/2G>IA$N<
-!Ki<5rrK`?r;R&L5j&+H4l>?\rr3&Z/Ed$4$gQ75s8UhXjo>?Hg\h'P<lXh4!J$a8rrX;AWH8(=
-"TI-TTmQe=$m#BJQu;Bms6)??OGs2="8^pTS,=c:AcD]17+hJ<&U0-*s8U)>s8Prqqu=?:s(8b>
-rrKN?qu7)+E;rqZs8VbKGlLIarr3#elMgebr7'^)rrG4?rr3"WP5YC]]jUO5!Tl<<rs0Y*.qmH"
-s8O,<rsE/Hs6;)ns8Q3>s*t~>
-"!.E>@K+aVr;Q`rJHPNDmOnJ<!C#B9rt+!Ns+Ppms8UV?s*^O>s62?6rrm5&e/6]nr;Qa;qYpcM
-e=;Er;p,+>!MXo6rr=);rrG.?rr3F`PlLb'g].;(SH&WV0`:qO+T;<>"6]4S55Zo5_Z/6Crr3"*
-^@hL,Lm7f:!Ip[5rrK*?rVloQ62gfch#5\orVlsEq8uV7rsUmKs8Sm*mJm2,s1)Y<rr^sSZ#'C=
-!$2";!Aj!5rrHE@rVmFi(nB+*^0^i/Nq35A.KBF4r$r%hs)j7ms8U&>rVlj<qu6[Ho(r@eju2l3
-!$2";!CPT?rs\;\s#T/u49(2%s"_RmrrI\?rr3&oeE6c1"\.)Cs,E*<rrViBl2L\d6/2G>IA$N<
-!Ki<5rrK`?r;R&L5j&+H4l>?\rr3&Z/Ed$4$gQ75s8UhXjo>?Hg\h'P<lXh4!J$a8rrX;AWH8(=
-"TI-TTmQe=$m#BJQu;Bms6)??OGs2="8^pTS,=c:AcD]17+hJ<&U0-*s8U)>s8Prqqu=?:s(8b>
-rrKN?qu7)+E;rqZs8VbKGlLIarr3#elMgebr7'^)rrG4?rr3"WP5YC]]jUO5!Tl<<rs0Y*.qmH"
-s8O,<rsE/Hs6;)ns8Q3>s*t~>
-"!.E>@K+aVr;Q`rJHPNDmOnJ<!C#B9rt+!Ns+Ppms8UV?s*^O>s62?6rrm5&e/6]nr;Qa;qYpcM
-e=;Er;p,+>!MXo6rr=);rrG.?rr3F`PlLb'g].;(SH&WV0`:qO+T;<>"6]4S55Zo5_Z/6Crr3"*
-^@hL,Lm7f:!Ip[5rrK*?rVloQ62gfch#5\orVlsEq8uV7rsUmKs8Sm*mJm2,s1)Y<rr^sSZ#'C=
-!$2";!Aj!5rrHE@rVmFi(nB+*^0^i/Nq35A.KBF4r$r%hs)j7ms8U&>rVlj<qu6[Ho(r@eju2l3
-!$2";!CPT?rs\;\s#T/u49(2%s"_RmrrI\?rr3&oeE6c1"\.)Cs,E*<rrViBl2L\d6/2G>IA$N<
-!Ki<5rrK`?r;R&L5j&+H4l>?\rr3&Z/Ed$4$gQ75s8UhXjo>?Hg\h'P<lXh4!J$a8rrX;AWH8(=
-"TI-TTmQe=$m#BJQu;Bms6)??OGs2="8^pTS,=c:AcD]17+hJ<&U0-*s8U)>s8Prqqu=?:s(8b>
-rrKN?qu7)+E;rqZs8VbKGlLIarr3#elMgebr7'^)rrG4?rr3"WP5YC]]jUO5!Tl<<rs0Y*.qmH"
-s8O,<rsE/Hs6;)ns8Q3>s*t~>
-"!.E>Fo)+AJXc]>rq-0h!C#B>rrMn@rZ)+Z5Q?G(rr38S8H4C6nF56up\tD5YlF#Po_e^h*VfX;
-WcJ,<(]GEU&pj9O!$2";!BD(t*<[.Hs8O,=rrr2os8VI?r;Qfh+9!8_PktFNr:'daqu6\'^@qR.
-Wd+@:rrIV?p&>&lF8c+>rO`"K"3gbn9)\bl,PfJ[rr3-]jo>@VGlI^FoDc@2qu6]%%/h1H.fB;I
-1[4T4!F<M>rt(6GqZ$TP56$WZ*??+'>Q=KrnH8IaFf56=!QA.=rr=):rrFV?qYpTY2Y@"L*W5p<
-ofW3o%!VLH3o]*[s,*$?1@+r>!J-a8rr=\N*WHZN[eTk&+9!8^%MHbZrrJ7?p&>')@Jp-+cqXN>
-"82WS3;rjX2<Xf8!S.q`*<HH`q>L<o<lXh4!J$a>rrMt`r>btZs8%lW*<[SWs.Of=rraABs-SK=
-rrhOCs,`3:rrDlmnGr7]rrGO?rVlnBVZ-T(``E->;9](?qtC&%(&f3V)0#WK;Z7[>'QF(PaSu2B
-Uj2q47/e2-Dts,-!B]9>rrJ%@[email protected]#ju3/;!ua,Xm/?qa')`gR'Ysb61B.:TpAFr@~>
-"!.E>Fo)+AJXc]>rq-0h!C#B>rrMn@rZ)+Z5Q?G(rr38S8H4C6nF56up\tD5YlF#Po_e^h*VfX;
-WcJ,<(]GEU&pj9O!$2";!BD(t*<[.Hs8O,=rrr2os8VI?r;Qfh+9!8_PktFNr:'daqu6\'^@qR.
-Wd+@:rrIV?p&>&lF8c+>rO`"K"3gbn9)\bl,PfJ[rr3-]jo>@VGlI^FoDc@2qu6]%%/h1H.fB;I
-1[4T4!F<M>rt(6GqZ$TP56$WZ*??+'>Q=KrnH8IaFf56=!QA.=rr=):rrFV?qYpTY2Y@"L*W5p<
-ofW3o%!VLH3o]*[s,*$?1@+r>!J-a8rr=\N*WHZN[eTk&+9!8^%MHbZrrJ7?p&>')@Jp-+cqXN>
-"82WS3;rjX2<Xf8!S.q`*<HH`q>L<o<lXh4!J$a>rrMt`r>btZs8%lW*<[SWs.Of=rraABs-SK=
-rrhOCs,`3:rrDlmnGr7]rrGO?rVlnBVZ-T(``E->;9](?qtC&%(&f3V)0#WK;Z7[>'QF(PaSu2B
-Uj2q47/e2-Dts,-!B]9>rrJ%@[email protected]#ju3/;!ua,Xm/?qa')`gR'Ysb61B.:TpAFr@~>
-"!.E>Fo)+AJXc]>rq-0h!C#B>rrMn@rZ)+Z5Q?G(rr38S8H4C6nF56up\tD5YlF#Po_e^h*VfX;
-WcJ,<(]GEU&pj9O!$2";!BD(t*<[.Hs8O,=rrr2os8VI?r;Qfh+9!8_PktFNr:'daqu6\'^@qR.
-Wd+@:rrIV?p&>&lF8c+>rO`"K"3gbn9)\bl,PfJ[rr3-]jo>@VGlI^FoDc@2qu6]%%/h1H.fB;I
-1[4T4!F<M>rt(6GqZ$TP56$WZ*??+'>Q=KrnH8IaFf56=!QA.=rr=):rrFV?qYpTY2Y@"L*W5p<
-ofW3o%!VLH3o]*[s,*$?1@+r>!J-a8rr=\N*WHZN[eTk&+9!8^%MHbZrrJ7?p&>')@Jp-+cqXN>
-"82WS3;rjX2<Xf8!S.q`*<HH`q>L<o<lXh4!J$a>rrMt`r>btZs8%lW*<[SWs.Of=rraABs-SK=
-rrhOCs,`3:rrDlmnGr7]rrGO?rVlnBVZ-T(``E->;9](?qtC&%(&f3V)0#WK;Z7[>'QF(PaSu2B
-Uj2q47/e2-Dts,-!B]9>rrJ%@[email protected]#ju3/;!ua,Xm/?qa')`gR'Ysb61B.:TpAFr@~>
-"!.E>Fo)+=JXcK8!C#B>s8S,ZrrrD25Q?G(rr35R8H7pi/1a!Yrs!;Ds8UtYjSf)Y*W?!=j7N?N
-"KHMB;p,+>!MXo6rrGC?rVlmYj8/cU*W#d@m4eS?kjSQ)rVln:Xn_nrf_tgN?G?F=!qFb*rVlrl
-R#h.E!q(Q@p&>&lF8c+>q;2)M""Woj9)\bl,PfJ[rr3-]jo>@VGl7RB\RYU<"5*XYD"mr11[4T4
-!F<M>rrJ1?rr3#U55bE]o-sG6#'Ggrs8U&>rVlj<qu6dKo)J:BrVlo\2Y@"L*W5p<htd9O%$HMJ
-3o]*[s,*$?1;s1l!J-a>rrVrDjneuXNK=&<!qat*qYpSET`"fjOc/o4!P;e<rrLJ@r;QfZ3<&pZ
-i@O0krrVK7o(r@e6/2>;!ER55rrIY@rVlo(C]=>:fH("]kPkJiq'?!6HiO-#)uor*K`:uSkV`C%
-N;ihXqVLrG#=R5EpYc'qVZ-T!``E->;9\t<!G8h<rt/POs8VeRE;rqZs8V_IGlQ^rrr3"hJc>ZN
-r6sX(rrucDs8VSDV>^Dp]jUO5!Tl<<rs0Y+/83N"s8O,9rrMC?qu;0~>
-"!.E>Fo)+=JXcK8!C#B>s8S,ZrrrD25Q?G(rr35R8H7pi/1a!Yrs!;Ds8UtYjSf)Y*W?!=j7N?N
-"KHMB;p,+>!MXo6rrGC?rVlmYj8/cU*W#d@m4eS?kjSQ)rVln:Xn_nrf_tgN?G?F=!qFb*rVlrl
-R#h.E!q(Q@p&>&lF8c+>q;2)M""Woj9)\bl,PfJ[rr3-]jo>@VGl7RB\RYU<"5*XYD"mr11[4T4
-!F<M>rrJ1?rr3#U55bE]o-sG6#'Ggrs8U&>rVlj<qu6dKo)J:BrVlo\2Y@"L*W5p<htd9O%$HMJ
-3o]*[s,*$?1;s1l!J-a>rrVrDjneuXNK=&<!qat*qYpSET`"fjOc/o4!P;e<rrLJ@r;QfZ3<&pZ
-i@O0krrVK7o(r@e6/2>;!ER55rrIY@rVlo(C]=>:fH("]kPkJiq'?!6HiO-#)uor*K`:uSkV`C%
-N;ihXqVLrG#=R5EpYc'qVZ-T!``E->;9\t<!G8h<rt/POs8VeRE;rqZs8V_IGlQ^rrr3"hJc>ZN
-r6sX(rrucDs8VSDV>^Dp]jUO5!Tl<<rs0Y+/83N"s8O,9rrMC?qu;0~>
-"!.E>Fo)+=JXcK8!C#B>s8S,ZrrrD25Q?G(rr35R8H7pi/1a!Yrs!;Ds8UtYjSf)Y*W?!=j7N?N
-"KHMB;p,+>!MXo6rrGC?rVlmYj8/cU*W#d@m4eS?kjSQ)rVln:Xn_nrf_tgN?G?F=!qFb*rVlrl
-R#h.E!q(Q@p&>&lF8c+>q;2)M""Woj9)\bl,PfJ[rr3-]jo>@VGl7RB\RYU<"5*XYD"mr11[4T4
-!F<M>rrJ1?rr3#U55bE]o-sG6#'Ggrs8U&>rVlj<qu6dKo)J:BrVlo\2Y@"L*W5p<htd9O%$HMJ
-3o]*[s,*$?1;s1l!J-a>rrVrDjneuXNK=&<!qat*qYpSET`"fjOc/o4!P;e<rrLJ@r;QfZ3<&pZ
-i@O0krrVK7o(r@e6/2>;!ER55rrIY@rVlo(C]=>:fH("]kPkJiq'?!6HiO-#)uor*K`:uSkV`C%
-N;ihXqVLrG#=R5EpYc'qVZ-T!``E->;9\t<!G8h<rt/POs8VeRE;rqZs8V_IGlQ^rrr3"hJc>ZN
-r6sX(rrucDs8VSDV>^Dp]jUO5!Tl<<rs0Y+/83N"s8O,9rrMC?qu;0~>
-"!.E><;j6._>jOdS,<3sfsWK(^&S,8L:4Ot5<o1%Qi@!feO]_7NW-?d`V9B5Cp<p=%(fsJe$c\"
-[^O]cMOa[S"Ho5R;p,+>!MXo6rrM@?rVln=WrBF,f`(mN*W#dAnm/]4I)#\h[JmT8GfBIX!*]?0
-!HHNdrrT>'N;`bW_HQg9!M+c5rrK*?rVlo[Ac9%>>P6lerO)f1qq5fb[KU*@s8Sm>r;QfBF8`NL
->Q;`frO2V'!Aj!5rrHE@rVlo%L&SL]W-/%<!V7c7rsa*)S[PttL]@D![M?6mrVm"5Z*os^rVlo\
-2Y@"L*W5p<Gc(JK%#:qa3o]FGs,*$?1.V>P!J%]ZrrUOIC&7i1NK=&<!l+e^qYpSET`"fjOc/o4
-!P;e<rrLJ@r;Qfa@K*\:C_,_.rrRiR[JKn(6/2>;!ER55rrIY@rVlo>GQ,#R<ZM.VHN(>]ZXWsI
-I^Z[i'EA*"K`:uSkV`CEL&SL]WH@k6#C<5TTn35fVZ-T!``E->;9\t<!Ki`J[M6pbs,3AT[\#9n
-s+R&Q[[]!qs*pdB[K2>`rr3&c!)NRn"CAOFOdu@L!PMn6rrM7?r;R$Cs8Tc(M<Y%DrO)jhs8V@>
-qu;0~>
-"!.E><;j6._>jOdS,<3sfsWK(^&S,8L:4Ot5<o1%Qi@!feO]_7NW-?d`V9B5Cp<p=%(fsJe$c\"
-[^O]cMOa[S"Ho5R;p,+>!MXo6rrM@?rVln=WrBF,f`(mN*W#dAnm/]4I)#\h[JmT8GfBIX!*]?0
-!HHNdrrT>'N;`bW_HQg9!M+c5rrK*?rVlo[Ac9%>>P6lerO)f1qq5fb[KU*@s8Sm>r;QfBF8`NL
->Q;`frO2V'!Aj!5rrHE@rVlo%L&SL]W-/%<!V7c7rsa*)S[PttL]@D![M?6mrVm"5Z*os^rVlo\
-2Y@"L*W5p<Gc(JK%#:qa3o]FGs,*$?1.V>P!J%]ZrrUOIC&7i1NK=&<!l+e^qYpSET`"fjOc/o4
-!P;e<rrLJ@r;Qfa@K*\:C_,_.rrRiR[JKn(6/2>;!ER55rrIY@rVlo>GQ,#R<ZM.VHN(>]ZXWsI
-I^Z[i'EA*"K`:uSkV`CEL&SL]WH@k6#C<5TTn35fVZ-T!``E->;9\t<!Ki`J[M6pbs,3AT[\#9n
-s+R&Q[[]!qs*pdB[K2>`rr3&c!)NRn"CAOFOdu@L!PMn6rrM7?r;R$Cs8Tc(M<Y%DrO)jhs8V@>
-qu;0~>
-"!.E><;j6._>jOdS,<3sfsWK(^&S,8L:4Ot5<o1%Qi@!feO]_7NW-?d`V9B5Cp<p=%(fsJe$c\"
-[^O]cMOa[S"Ho5R;p,+>!MXo6rrM@?rVln=WrBF,f`(mN*W#dAnm/]4I)#\h[JmT8GfBIX!*]?0
-!HHNdrrT>'N;`bW_HQg9!M+c5rrK*?rVlo[Ac9%>>P6lerO)f1qq5fb[KU*@s8Sm>r;QfBF8`NL
->Q;`frO2V'!Aj!5rrHE@rVlo%L&SL]W-/%<!V7c7rsa*)S[PttL]@D![M?6mrVm"5Z*os^rVlo\
-2Y@"L*W5p<Gc(JK%#:qa3o]FGs,*$?1.V>P!J%]ZrrUOIC&7i1NK=&<!l+e^qYpSET`"fjOc/o4
-!P;e<rrLJ@r;Qfa@K*\:C_,_.rrRiR[JKn(6/2>;!ER55rrIY@rVlo>GQ,#R<ZM.VHN(>]ZXWsI
-I^Z[i'EA*"K`:uSkV`CEL&SL]WH@k6#C<5TTn35fVZ-T!``E->;9\t<!Ki`J[M6pbs,3AT[\#9n
-s+R&Q[[]!qs*pdB[K2>`rr3&c!)NRn"CAOFOdu@L!PMn6rrM7?r;R$Cs8Tc(M<Y%DrO)jhs8V@>
-qu;0~>
-!Zh<`r+6(Zs8TIDqu6Z!ral.Qrr38'AnGcCN;p?%rr3,`OoNUMral1M\bQ1*VpPGC"4j.FUASU*
-V>pRRral;$s8SGCrr3#>YP.ttno2/<rr@6AAcSt4rr@9=rr_7mB".d>!,):C!5/(+!;?A'!65!;
-!mYDhrVloQSGW<fj+Xf2rs,MlR@3@?s4I9^"6KR_e,<k\lMpn0ral>jGQ7]bY5A5!_u40Lq>^K/
-rFQ<6s8UK7R31\drrZPJRA9c]!36$1!."[email protected];Qh8As<5o"1">P
-2Y@"O(n$f.rr2tGral;2s8RrDrr3,2^AftMral/8rVlrZAu5A(!P?#CrrUkcYPS8)Z,ZhDp6h=M
-MtR)U]/uFKj8]/>Pl(I\hYq*gc8FearrTT?e,'(MNTpKChjKlh`qB?:J6nY3qu?]2ral<"GQ7]S
-ral.Frr383AnL-Fs8TpCrr3,kL&_1Rral.Uo`#,DAqU-`Xi^SB"l5XIs-DU?rrA2\AcS"nrt(-$
-AqnR0s8RjdArFa5s8R]MAcSS(rrVe(Q2L[^AcS:urr]!`EFAJ>#Nd.sRF;-8GQ%ODV:,D=rFQ2O
-s8VYCqu;0~>
-!Zh<`r+6(Zs8TIDqu6Z!ral.Qrr38'AnGcCN;p?%rr3,`OoNUMral1M\bQ1*VpPGC"4j.FUASU*
-V>pRRral;$s8SGCrr3#>YP.ttno2/<rr@6AAcSt4rr@9=rr_7mB".d>!,):C!5/(+!;?A'!65!;
-!mYDhrVloQSGW<fj+Xf2rs,MlR@3@?s4I9^"6KR_e,<k\lMpn0ral>jGQ7]bY5A5!_u40Lq>^K/
-rFQ<6s8UK7R31\drrZPJRA9c]!36$1!."[email protected];Qh8As<5o"1">P
-2Y@"O(n$f.rr2tGral;2s8RrDrr3,2^AftMral/8rVlrZAu5A(!P?#CrrUkcYPS8)Z,ZhDp6h=M
-MtR)U]/uFKj8]/>Pl(I\hYq*gc8FearrTT?e,'(MNTpKChjKlh`qB?:J6nY3qu?]2ral<"GQ7]S
-ral.Frr383AnL-Fs8TpCrr3,kL&_1Rral.Uo`#,DAqU-`Xi^SB"l5XIs-DU?rrA2\AcS"nrt(-$
-AqnR0s8RjdArFa5s8R]MAcSS(rrVe(Q2L[^AcS:urr]!`EFAJ>#Nd.sRF;-8GQ%ODV:,D=rFQ2O
-s8VYCqu;0~>
-!Zh<`r+6(Zs8TIDqu6Z!ral.Qrr38'AnGcCN;p?%rr3,`OoNUMral1M\bQ1*VpPGC"4j.FUASU*
-V>pRRral;$s8SGCrr3#>YP.ttno2/<rr@6AAcSt4rr@9=rr_7mB".d>!,):C!5/(+!;?A'!65!;
-!mYDhrVloQSGW<fj+Xf2rs,MlR@3@?s4I9^"6KR_e,<k\lMpn0ral>jGQ7]bY5A5!_u40Lq>^K/
-rFQ<6s8UK7R31\drrZPJRA9c]!36$1!."[email protected];Qh8As<5o"1">P
-2Y@"O(n$f.rr2tGral;2s8RrDrr3,2^AftMral/8rVlrZAu5A(!P?#CrrUkcYPS8)Z,ZhDp6h=M
-MtR)U]/uFKj8]/>Pl(I\hYq*gc8FearrTT?e,'(MNTpKChjKlh`qB?:J6nY3qu?]2ral<"GQ7]S
-ral.Frr383AnL-Fs8TpCrr3,kL&_1Rral.Uo`#,DAqU-`Xi^SB"l5XIs-DU?rrA2\AcS"nrt(-$
-AqnR0s8RjdArFa5s8R]MAcSS(rrVe(Q2L[^AcS:urr]!`EFAJ>#Nd.sRF;-8GQ%ODV:,D=rFQ2O
-s8VYCqu;0~>
-!$0_l!I^U>rrL>?c2Rh,WkJE5h6Z_Q!7h($!9VW-!65"j!;,sa"0dE1O3[b-Tn@ugo`##OK7gQ"
-rrFn@g]%9Grdt3jp&>$Krdt4,o)A_JkOAKOfD^C&j7WEP_>]&eqXFLccb08W!$.[2"-%qcZ1\+s
-oDX@BaQNSR~>
-!$0_l!I^U>rrL>?c2Rh,WkJE5h6Z_Q!7h($!9VW-!65"j!;,sa"0dE1O3[b-Tn@ugo`##OK7gQ"
-rrFn@g]%9Grdt3jp&>$Krdt4,o)A_JkOAKOfD^C&j7WEP_>]&eqXFLccb08W!$.[2"-%qcZ1\+s
-oDX@BaQNSR~>
-!$0_l!I^U>rrL>?c2Rh,WkJE5h6Z_Q!7h($!9VW-!65"j!;,sa"0dE1O3[b-Tn@ugo`##OK7gQ"
-rrFn@g]%9Grdt3jp&>$Krdt4,o)A_JkOAKOfD^C&j7WEP_>]&eqXFLccb08W!$.[2"-%qcZ1\+s
-oDX@BaQNSR~>
-!$0_l!R>og?NFuWJcC<$dJj5&laHfo2<W*]!Si8*?N?dNs6ou<~>
-!$0_l!R>og?NFuWJcC<$dJj5&laHfo2<W*]!Si8*?N?dNs6ou<~>
-!$0_l!R>og?NFuWJcC<$dJj5&laHfo2<W*]!Si8*?N?dNs6ou<~>
-!$0\k!7h(]!6TlmJcF*s!Qk2HrrL:<aSu7trk&7.JcG3=J,~>
-!$0\k!7h(]!6TlmJcF*s!Qk2HrrL:<aSu7trk&7.JcG3=J,~>
-!$0\k!7h(]!6TlmJcF*s!Qk2HrrL:<aSu7trk&7.JcG3=J,~>
-!$..#"#_JQH%H!Hs+13$s7lVE~>
-!$..#"#_JQH%H!Hs+13$s7lVE~>
-!$..#"#_JQH%H!Hs+13$s7lVE~>
-!$1P.",Is-hrXk>C)m`\rrQ[N'D)5,m2m?Wo_8@e73")Lrr`#hZsnUdJcC<$JcGNFJ,~>
-!$1P.",Is-hrXk>C)m`\rrQ[N'D)5,m2m?Wo_8@e73")Lrr`#hZsnUdJcC<$JcGNFJ,~>
-!$1P.",Is-hrXk>C)m`\rrQ[N'D)5,m2m?Wo_8@e73")Lrr`#hZsnUdJcC<$JcGNFJ,~>
-!$1J,!C#B#rr=)9rr=)2rraJBs/L,5rrMX?lMgms@Y+Q1s+13$s7lVE~>
-!$1J,!C#B#rr=)9rr=)2rraJBs/L,5rrMX?lMgms@Y+Q1s+13$s7lVE~>
-!$1J,!C#B#rr=)9rr=)2rraJBs/L,5rrMX?lMgms@Y+Q1s+13$s7lVE~>
-#9Ej*e^C_-[/U(*g&A5V[f$.+52Q#5"kqkTZ*D%BrrC@DYlMW<rr=)9rr=)9rrKOBr;R!Er;X^+
-s8Tq7YlN)JrrMX?r;Qc0rilIPrr2u0rilIRr;Qf0@Y+Q1s+13$s7lVE~>
-#9Ej*e^C_-[/U(*g&A5V[f$.+52Q#5"kqkTZ*D%BrrC@DYlMW<rr=)9rr=)9rrKOBr;R!Er;X^+
-s8Tq7YlN)JrrMX?r;Qc0rilIPrr2u0rilIRr;Qf0@Y+Q1s+13$s7lVE~>
-#9Ej*e^C_-[/U(*g&A5V[f$.+52Q#5"kqkTZ*D%BrrC@DYlMW<rr=)9rr=)9rrKOBr;R!Er;X^+
-s8Tq7YlN)JrrMX?r;Qc0rilIPrr2u0rilIRr;Qf0@Y+Q1s+13$s7lVE~>
-$Q]8F7!rccCo%*_JGs<bDQ*O6!C#B6rs=B]GACu7ZN&$mrbDOU[f-4+*W#d9*W#d:$nqPY!?h=<
-rr@rUCB8b%rr3#h/,fJKY]9YX"F\VrXDe)R!IiJqrrK`@JcC<$JcC<$q#>j~>
-$Q]8F7!rccCo%*_JGs<bDQ*O6!C#B6rs=B]GACu7ZN&$mrbDOU[f-4+*W#d9*W#d:$nqPY!?h=<
-rr@rUCB8b%rr3#h/,fJKY]9YX"F\VrXDe)R!IiJqrrK`@JcC<$JcC<$q#>j~>
-$Q]8F7!rccCo%*_JGs<bDQ*O6!C#B6rs=B]GACu7ZN&$mrbDOU[f-4+*W#d9*W#d:$nqPY!?h=<
-rr@rUCB8b%rr3#h/,fJKY]9YX"F\VrXDe)R!IiJqrrK`@JcC<$JcC<$q#>j~>
-$Q]8F50X',pEop4IfB?JmOnJ<!C#B>rrBt7G70i=Ki$S)s4'[?I@pN=!R+C=rr=)9rr=)9rrJ+N
-rr3,"G7Sk^q>UJiHN*pFnLOS<!CGQ?rrgQfs#K-=rrIq?rVlo1@Y+Q1s+13$s7lVE~>
-$Q]8F50X',pEop4IfB?JmOnJ<!C#B>rrBt7G70i=Ki$S)s4'[?I@pN=!R+C=rr=)9rr=)9rrJ+N
-rr3,"G7Sk^q>UJiHN*pFnLOS<!CGQ?rrgQfs#K-=rrIq?rVlo1@Y+Q1s+13$s7lVE~>
-$Q]8F50X',pEop4IfB?JmOnJ<!C#B>rrBt7G70i=Ki$S)s4'[?I@pN=!R+C=rr=)9rr=)9rrJ+N
-rr3,"G7Sk^q>UJiHN*pFnLOS<!CGQ?rrgQfs#K-=rrIq?rVlo1@Y+Q1s+13$s7lVE~>
-"!.E>FoMCDpEop4/cJoS<%e.L!C#B>rrC[KV$"@0KpVf="P$'CI@pN=!R+C=rr=)9rr=)4rrg<;
-'r/;;rr@KH=ogX0rr3#h/,fJK]Oh(G"JPkq3DocZ!AKc:rrK`@JcC<$JcC<$q#>j~>
-"!.E>FoMCDpEop4/cJoS<%e.L!C#B>rrC[KV$"@0KpVf="P$'CI@pN=!R+C=rr=)9rr=)4rrg<;
-'r/;;rr@KH=ogX0rr3#h/,fJK]Oh(G"JPkq3DocZ!AKc:rrK`@JcC<$JcC<$q#>j~>
-"!.E>FoMCDpEop4/cJoS<%e.L!C#B>rrC[KV$"@0KpVf="P$'CI@pN=!R+C=rr=)9rr=)4rrg<;
-'r/;;rr@KH=ogX0rr3#h/,fJK]Oh(G"JPkq3DocZ!AKc:rrK`@JcC<$JcC<$q#>j~>
-"!.E>FoMCDpEop4?i@e@c2IYC52Q#5!JQm>rrgkCs*^O=rrL>?rVlj<qYpO9oD\h6r;HWrI&?nZ
-!IK.lrrMX?r;Qc>rkS_oVuJcYrP8KqrVlo1@Y+Q1s+13$s7lVE~>
-"!.E>FoMCDpEop4?i@e@c2IYC52Q#5!JQm>rrgkCs*^O=rrL>?rVlj<qYpO9oD\h6r;HWrI&?nZ
-!IK.lrrMX?r;Qc>rkS_oVuJcYrP8KqrVlo1@Y+Q1s+13$s7lVE~>
-"!.E>FoMCDpEop4?i@e@c2IYC52Q#5!JQm>rrgkCs*^O=rrL>?rVlj<qYpO9oD\h6r;HWrI&?nZ
-!IK.lrrMX?r;Qc>rkS_oVuJcYrP8KqrVlo1@Y+Q1s+13$s7lVE~>
-"!.E>FoMCDpEop4Ie`pD52Q#5$&'&,s8UV?s*^O=rrL>?rVlj<qYpO9qYpRH9)S\i+T23<##i\E
-s2Pk#rr3#h/,fJK>2T>Z"HeWB3TKo7!P;fls+13$s+14Fs*t~>
-"!.E>FoMCDpEop4Ie`pD52Q#5$&'&,s8UV?s*^O=rrL>?rVlj<qYpO9qYpRH9)S\i+T23<##i\E
-s2Pk#rr3#h/,fJK>2T>Z"HeWB3TKo7!P;fls+13$s+14Fs*t~>
-"!.E>FoMCDpEop4Ie`pD52Q#5$&'&,s8UV?s*^O=rrL>?rVlj<qYpO9qYpRH9)S\i+T23<##i\E
-s2Pk#rr3#h/,fJK>2T>Z"HeWB3TKo7!P;fls+13$s+14Fs*t~>
-"!.EGKDtlRpH/ESNrC%!/H5YPL`IBR1\^nUKp>sb*CB](rG_`V#YFsos(WPm*Duh9"CiGj*Ei=?
-!@1&1rrG%UrVmK-9-#$QWJCNR73*9eGQ7^@4oQH)IJs3D2?"TrLAq2TkiSgQJcC<$JcC<$q#>j~>
-"!.EGKDtlRpH/ESNrC%!/H5YPL`IBR1\^nUKp>sb*CB](rG_`V#YFsos(WPm*Duh9"CiGj*Ei=?
-!@1&1rrG%UrVmK-9-#$QWJCNR73*9eGQ7^@4oQH)IJs3D2?"TrLAq2TkiSgQJcC<$JcC<$q#>j~>
-"!.EGKDtlRpH/ESNrC%!/H5YPL`IBR1\^nUKp>sb*CB](rG_`V#YFsos(WPm*Duh9"CiGj*Ei=?
-!@1&1rrG%UrVmK-9-#$QWJCNR73*9eGQ7^@4oQH)IJs3D2?"TrLAq2TkiSgQJcC<$JcC<$q#>j~>
-!$1"t!JQlGrrY\J2M6S\JcC<$JcGNFJ,~>
-!$1"t!JQlGrrY\J2M6S\JcC<$JcGNFJ,~>
-!$1"t!JQlGrrY\J2M6S\JcC<$JcGNFJ,~>
-!$1"t!JQkks+13$s+13Hs*t~>
-!$1"t!JQkks+13$s+13Hs*t~>
-!$1"t!JQkks+13$s+13Hs*t~>
-!$1"t!P?=%s+13$s+13Hs*t~>
-!$1"t!P?=%s+13$s+13Hs*t~>
-!$1"t!P?=%s+13$s+13Hs*t~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$.@)!V"X)rrM*>JcC<$JcFU,J,~>
-!$.@)!V"X)rrM*>JcC<$JcFU,J,~>
-!$.@)!V"X)rrM*>JcC<$JcFU,J,~>
-!Zh<ur1X1qq#:BJe+3M@aJ,F)rVlu=U8%SZrrL7$rr3)_`W*sUU&`:0rrBk4U&`O-rrVhUQM1=Z
-Z2;uL!p66)pAY0d\+'Cuce\R"!9*mN!;6?k!jdU@JcC<$JcFX-J,~>
-!Zh<ur1X1qq#:BJe+3M@aJ,F)rVlu=U8%SZrrL7$rr3)_`W*sUU&`:0rrBk4U&`O-rrVhUQM1=Z
-Z2;uL!p66)pAY0d\+'Cuce\R"!9*mN!;6?k!jdU@JcC<$JcFX-J,~>
-!Zh<ur1X1qq#:BJe+3M@aJ,F)rVlu=U8%SZrrL7$rr3)_`W*sUU&`:0rrBk4U&`O-rrVhUQM1=Z
-Z2;uL!p66)pAY0d\+'Cuce\R"!9*mN!;6?k!jdU@JcC<$JcFX-J,~>
-"!.E>3;n.'NqiVTQA4u1"0d(en,<7gXEkNRpAY/0Yl=Y*]4(_L=T*OGZ2">!V>Y]@9mZ7-!T6*5
-rrFP?lMgnMW9aHbgNpR2rrLi`rVloY3V!+Sc@:E's8V55rH\HtrVln5Z@W%,s+14-s*t~>
-"!.E>3;n.'NqiVTQA4u1"0d(en,<7gXEkNRpAY/0Yl=Y*]4(_L=T*OGZ2">!V>Y]@9mZ7-!T6*5
-rrFP?lMgnMW9aHbgNpR2rrLi`rVloY3V!+Sc@:E's8V55rH\HtrVln5Z@W%,s+14-s*t~>
-"!.E>3;n.'NqiVTQA4u1"0d(en,<7gXEkNRpAY/0Yl=Y*]4(_L=T*OGZ2">!V>Y]@9mZ7-!T6*5
-rrFP?lMgnMW9aHbgNpR2rrLi`rVloY3V!+Sc@:E's8V55rH\HtrVln5Z@W%,s+14-s*t~>
-"!.E>Fn>V6QA4o/!A3d;rrFG?pAY/0Yl=Y*]4(_L\aTP"fm1^.rrW1;YP%nr..lg)!RjX#rrKB?
-rVloY3V*1UdsK?QFR&nK;Z6UqU](2o_KOsjs+13$s5<p-~>
-"!.E>Fn>V6QA4o/!A3d;rrFG?pAY/0Yl=Y*]4(_L\aTP"fm1^.rrW1;YP%nr..lg)!RjX#rrKB?
-rVloY3V*1UdsK?QFR&nK;Z6UqU](2o_KOsjs+13$s5<p-~>
-"!.E>Fn>V6QA4o/!A3d;rrFG?pAY/0Yl=Y*]4(_L\aTP"fm1^.rrW1;YP%nr..lg)!RjX#rrKB?
-rVloY3V*1UdsK?QFR&nK;Z6UqU](2o_KOsjs+13$s5<p-~>
-"!.E>Fo)+<VuB<p=9&;dL5\bu?2jj(S,Q%\A,Q?-/arT:!@@L6rsdIoh#HGJd/RUdBM2!LoD\j+
-?1.^nrZD%;!*T:o"Ju.u.-LS&!3?,!!)<Gc&@)98@/nYJ9=Os$<^%9l9>1-#!WHO+rs")2s5QaF
-V>gK%nk1e^92!h8j#P!U9*!]@rs@Uudf9?f>5QH?p\t7gd"24Js+14.s*t~>
-"!.E>Fo)+<VuB<p=9&;dL5\bu?2jj(S,Q%\A,Q?-/arT:!@@L6rsdIoh#HGJd/RUdBM2!LoD\j+
-?1.^nrZD%;!*T:o"Ju.u.-LS&!3?,!!)<Gc&@)98@/nYJ9=Os$<^%9l9>1-#!WHO+rs")2s5QaF
-V>gK%nk1e^92!h8j#P!U9*!]@rs@Uudf9?f>5QH?p\t7gd"24Js+14.s*t~>
-"!.E>Fo)+<VuB<p=9&;dL5\bu?2jj(S,Q%\A,Q?-/arT:!@@L6rsdIoh#HGJd/RUdBM2!LoD\j+
-?1.^nrZD%;!*T:o"Ju.u.-LS&!3?,!!)<Gc&@)98@/nYJ9=Os$<^%9l9>1-#!WHO+rs")2s5QaF
-V>gK%nk1e^92!h8j#P!U9*!]@rs@Uudf9?f>5QH?p\t7gd"24Js+14.s*t~>
-"!.E>(&ffgmf3<kIf@_'``2u((m`Rs^g$i5M>km']41a=!A3d;rrFG?p&>IscMuQcs8QRQ\'`Tr
-L%YHIj&b4-rrN*@qu6ZGrm:k!Y5]n0rm:jp[JreDrm;:"]`6A3=4,E7_uJ2f4OMREq#:Bn+8u3D
-:!`k7d=?cHrsJ\OO]TrXo`*qYAcC'X:[RuX!VbILrr^mPb#8!6!DUpls+13$s5<p-~>
-"!.E>(&ffgmf3<kIf@_'``2u((m`Rs^g$i5M>km']41a=!A3d;rrFG?p&>IscMuQcs8QRQ\'`Tr
-L%YHIj&b4-rrN*@qu6ZGrm:k!Y5]n0rm:jp[JreDrm;:"]`6A3=4,E7_uJ2f4OMREq#:Bn+8u3D
-:!`k7d=?cHrsJ\OO]TrXo`*qYAcC'X:[RuX!VbILrr^mPb#8!6!DUpls+13$s5<p-~>
-"!.E>(&ffgmf3<kIf@_'``2u((m`Rs^g$i5M>km']41a=!A3d;rrFG?p&>IscMuQcs8QRQ\'`Tr
-L%YHIj&b4-rrN*@qu6ZGrm:k!Y5]n0rm:jp[JreDrm;:"]`6A3=4,E7_uJ2f4OMREq#:Bn+8u3D
-:!`k7d=?cHrsJ\OO]TrXo`*qYAcC'X:[RuX!VbILrr^mPb#8!6!DUpls+13$s5<p-~>
-"!.E>D>ro*rr<"nIfAsJoC;jHIJNpCju<=#M#R#Idm*g2!A3d;rrFG?p&>J%a8XI[s8V`Yr;Zf'
-C%_K,e4B!,!WF2<rrD`koE9K1s!Zt-rrdSCruh:>rs`nKs7mi/s8QrHs8UP>p&>9q+9/Bms%Ui=
-rrJ[@r;Qf&C]487j#-H-rrFt?nc&g9;ZHc1*>SMP!DUpls+13$s5<p-~>
-"!.E>D>ro*rr<"nIfAsJoC;jHIJNpCju<=#M#R#Idm*g2!A3d;rrFG?p&>J%a8XI[s8V`Yr;Zf'
-C%_K,e4B!,!WF2<rrD`koE9K1s!Zt-rrdSCruh:>rs`nKs7mi/s8QrHs8UP>p&>9q+9/Bms%Ui=
-rrJ[@r;Qf&C]487j#-H-rrFt?nc&g9;ZHc1*>SMP!DUpls+13$s5<p-~>
-"!.E>D>ro*rr<"nIfAsJoC;jHIJNpCju<=#M#R#Idm*g2!A3d;rrFG?p&>J%a8XI[s8V`Yr;Zf'
-C%_K,e4B!,!WF2<rrD`koE9K1s!Zt-rrdSCruh:>rs`nKs7mi/s8QrHs8UP>p&>9q+9/Bms%Ui=
-rrJ[@r;Qf&C]487j#-H-rrFt?nc&g9;ZHc1*>SMP!DUpls+13$s5<p-~>
-"!.E>Fo)+<Q2W071uA7uLAq2Uju<=#(B#W]?2ad(/arT:!@@L4rrOq7-MdZBZYB.5!W"&-rrN*@
-r;QfS2?#!,'V,1Oo`"jnGbtE_rVlg"Dls'8,PqE@dn064#Q5bEV0Dr6ci3qFSUgY<!O6G=rrM.?
-rVlmTkjeZRb#83<!$2";!DUpls+13$s5<p-~>
-"!.E>Fo)+<Q2W071uA7uLAq2Uju<=#(B#W]?2ad(/arT:!@@L4rrOq7-MdZBZYB.5!W"&-rrN*@
-r;QfS2?#!,'V,1Oo`"jnGbtE_rVlg"Dls'8,PqE@dn064#Q5bEV0Dr6ci3qFSUgY<!O6G=rrM.?
-rVlmTkjeZRb#83<!$2";!DUpls+13$s5<p-~>
-"!.E>Fo)+<Q2W071uA7uLAq2Uju<=#(B#W]?2ad(/arT:!@@L4rrOq7-MdZBZYB.5!W"&-rrN*@
-r;QfS2?#!,'V,1Oo`"jnGbtE_rVlg"Dls'8,PqE@dn064#Q5bEV0Dr6ci3qFSUgY<!O6G=rrM.?
-rVlmTkjeZRb#83<!$2";!DUpls+13$s5<p-~>
-"!.E>Fo21>jkTk8"R[oBQA5D="QhZCNfNo7!A3d;rrFG?o`"tIi[4[)!S-Q9rrKH?rVlo1ao)/>
-^0^1+!rc-@rVm0Ym/R+I?(CpC\,QC1GbtE_rVlg"Dls'8,PqEDdn0T>e*Zu2#Q5b5OaQ._ci3qF
-SUgY<#I/(Es2t)r3W8sY2!FK0!Qn==rr=)<rrUech1>TWs+14.s*t~>
-"!.E>Fo21>jkTk8"R[oBQA5D="QhZCNfNo7!A3d;rrFG?o`"tIi[4[)!S-Q9rrKH?rVlo1ao)/>
-^0^1+!rc-@rVm0Ym/R+I?(CpC\,QC1GbtE_rVlg"Dls'8,PqEDdn0T>e*Zu2#Q5b5OaQ._ci3qF
-SUgY<#I/(Es2t)r3W8sY2!FK0!Qn==rr=)<rrUech1>TWs+14.s*t~>
-"!.E>Fo21>jkTk8"R[oBQA5D="QhZCNfNo7!A3d;rrFG?o`"tIi[4[)!S-Q9rrKH?rVlo1ao)/>
-^0^1+!rc-@rVm0Ym/R+I?(CpC\,QC1GbtE_rVlg"Dls'8,PqEDdn0T>e*Zu2#Q5b5OaQ._ci3qF
-SUgY<#I/(Es2t)r3W8sY2!FK0!Qn==rr=)<rrUech1>TWs+14.s*t~>
-"!.E>8H#(]XT-4grga1[IfG^grr3,`2ugF@rga%hrr3,?SK*iqrr3,<SJRZup&>)DQ?rQ1!M>AN
-SH4YDrVlm#2uN[U*U<Y*i&pu<$%SG7SVAkhs!V@USHOD^s)sq3SHO>bs7mo9rrqJ)SXk#Wq>Us(
-Boe[jKQQ2Qn=<r_S`TkN#L@afST*rU3W8sY2!FK0!T%ttSH*F'rrHl?JcC<$JcFX-J,~>
-"!.E>8H#(]XT-4grga1[IfG^grr3,`2ugF@rga%hrr3,?SK*iqrr3,<SJRZup&>)DQ?rQ1!M>AN
-SH4YDrVlm#2uN[U*U<Y*i&pu<$%SG7SVAkhs!V@USHOD^s)sq3SHO>bs7mo9rrqJ)SXk#Wq>Us(
-Boe[jKQQ2Qn=<r_S`TkN#L@afST*rU3W8sY2!FK0!T%ttSH*F'rrHl?JcC<$JcFX-J,~>
-"!.E>8H#(]XT-4grga1[IfG^grr3,`2ugF@rga%hrr3,?SK*iqrr3,<SJRZup&>)DQ?rQ1!M>AN
-SH4YDrVlm#2uN[U*U<Y*i&pu<$%SG7SVAkhs!V@USHOD^s)sq3SHO>bs7mo9rrqJ)SXk#Wq>Us(
-Boe[jKQQ2Qn=<r_S`TkN#L@afST*rU3W8sY2!FK0!T%ttSH*F'rrHl?JcC<$JcFX-J,~>
-!Zh<ir-ng3s8Tn6IftQ,s2r4Xrrhn]s8TS-IfPT0rrBD)IfP`4rrB8%IfPl.rrA)WrrAemIfQ>C
-rrIY>r;QbWlMgqTJ$&\L#`4%\YeSH_POSR$!5ng9!.b&u"NUQBr/pgT"586Sd.dPGn"'LY[+PEY
-lhu;5h#76Waa\g!s7)TWrrJP[nG`L>rI4h<rr3&;J(]DQJcC<$huA3~>
-!Zh<ir-ng3s8Tn6IftQ,s2r4Xrrhn]s8TS-IfPT0rrBD)IfP`4rrB8%IfPl.rrA)WrrAemIfQ>C
-rrIY>r;QbWlMgqTJ$&\L#`4%\YeSH_POSR$!5ng9!.b&u"NUQBr/pgT"586Sd.dPGn"'LY[+PEY
-lhu;5h#76Waa\g!s7)TWrrJP[nG`L>rI4h<rr3&;J(]DQJcC<$huA3~>
-!Zh<ir-ng3s8Tn6IftQ,s2r4Xrrhn]s8TS-IfPT0rrBD)IfP`4rrB8%IfPl.rrA)WrrAemIfQ>C
-rrIY>r;QbWlMgqTJ$&\L#`4%\YeSH_POSR$!5ng9!.b&u"NUQBr/pgT"586Sd.dPGn"'LY[+PEY
-lhu;5h#76Waa\g!s7)TWrrJP[nG`L>rI4h<rr3&;J(]DQJcC<$huA3~>
-!$.@)!U.7_rrLKtJcC<$JcFU,J,~>
-!$.@)!U.7_rrLKtJcC<$JcFU,J,~>
-!$.@)!U.7_rrLKtJcC<$JcFU,J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$2%<!VH<grrMlioD\pdn*g5QrrVf\rndYUo_[nQ"9.cXpAP!ln+6&K!VZ?grrW(rKA$8/oDJXg
-qX=1=rrMiio`#!en,'Hk!THTHrrG4Kqu6[UnU^^ks2P(h~>
-!$2%<!VH<grrMlioD\pdn*g5QrrVf\rndYUo_[nQ"9.cXpAP!ln+6&K!VZ?grrW(rKA$8/oDJXg
-qX=1=rrMiio`#!en,'Hk!THTHrrG4Kqu6[UnU^^ks2P(h~>
-!$2%<!VH<grrMlioD\pdn*g5QrrVf\rndYUo_[nQ"9.cXpAP!ln+6&K!VZ?grrW(rKA$8/oDJXg
-qX=1=rrMiio`#!en,'Hk!THTHrrG4Kqu6[UnU^^ks2P(h~>
-!$2(=!p)_mrVlqdOn//E",\Z;k5>5\CG#,LrrLpOmJd2k_<Lt+`@WZ`lMpn`/RS#I!I1I?rrL/?
-f`).EfDklc/Y1u&!pa0mo`"uX/]ZZH!TE_;rrLpOo)A\1qYpO9qu6]o,(]cFs2P(h~>
-!$2(=!p)_mrVlqdOn//E",\Z;k5>5\CG#,LrrLpOmJd2k_<Lt+`@WZ`lMpn`/RS#I!I1I?rrL/?
-f`).EfDklc/Y1u&!pa0mo`"uX/]ZZH!TE_;rrLpOo)A\1qYpO9qu6]o,(]cFs2P(h~>
-!$2(=!p)_mrVlqdOn//E",\Z;k5>5\CG#,LrrLpOmJd2k_<Lt+`@WZ`lMpn`/RS#I!I1I?rrL/?
-f`).EfDklc/Y1u&!pa0mo`"uX/]ZZH!TE_;rrLpOo)A\1qYpO9qu6]o,(]cFs2P(h~>
-"s*aDh09a\r;Qh\Qh0hK!B0*,rrG1?mJd2k_<Lt&*WQ/%MsLBIGbtH?pRR)lrrGR?i;WoBL*<S@
-rrH*?li-uIiUd'M_-?d9!Ed>=rrW+#a+=8As2Y.i~>
-"s*aDh09a\r;Qh\Qh0hK!B0*,rrG1?mJd2k_<Lt&*WQ/%MsLBIGbtH?pRR)lrrGR?i;WoBL*<S@
-rrH*?li-uIiUd'M_-?d9!Ed>=rrW+#a+=8As2Y.i~>
-"s*aDh09a\r;Qh\Qh0hK!B0*,rrG1?mJd2k_<Lt&*WQ/%MsLBIGbtH?pRR)lrrGR?i;WoBL*<S@
-rrH*?li-uIiUd'M_-?d9!Ed>=rrW+#a+=8As2Y.i~>
-"s*a!J\Fq)qu6_[OS\VL!B0*=rr^-*R/$X[!5JN##d+.,a-\'+R'?Si!4`#q!42V'!M-:jrrH??
-rr3,W`rH(Arg3u*s8TOps8V)prVm0Es8TdDs8Sj]Yl4S&XRlFY!6bBA$(RBM_g&$Xs5Z0;rrE#r
-Qiu"?s.o&]Qil%As7ZDY"5NqVo)4pXi;`iGrg3rB7G%S*R$c5!rrVhrh#<ZClMpnGrg3cHWqlJj
-"R:fBEiSg4"4rp-jSf)YeGYd4rrT]tpAY'lc2O(5o;_ijao7Y5UAt8AQnilQV>gJp_Z#o6WW3"A
-fX$s4XT/=@Qm7?QYl=Y&\GhiqZi0n).e<H9!Tl<;rrLq?JcC<$a8^Y~>
-"s*a!J\Fq)qu6_[OS\VL!B0*=rr^-*R/$X[!5JN##d+.,a-\'+R'?Si!4`#q!42V'!M-:jrrH??
-rr3,W`rH(Arg3u*s8TOps8V)prVm0Es8TdDs8Sj]Yl4S&XRlFY!6bBA$(RBM_g&$Xs5Z0;rrE#r
-Qiu"?s.o&]Qil%As7ZDY"5NqVo)4pXi;`iGrg3rB7G%S*R$c5!rrVhrh#<ZClMpnGrg3cHWqlJj
-"R:fBEiSg4"4rp-jSf)YeGYd4rrT]tpAY'lc2O(5o;_ijao7Y5UAt8AQnilQV>gJp_Z#o6WW3"A
-fX$s4XT/=@Qm7?QYl=Y&\GhiqZi0n).e<H9!Tl<;rrLq?JcC<$a8^Y~>
-"s*a!J\Fq)qu6_[OS\VL!B0*=rr^-*R/$X[!5JN##d+.,a-\'+R'?Si!4`#q!42V'!M-:jrrH??
-rr3,W`rH(Arg3u*s8TOps8V)prVm0Es8TdDs8Sj]Yl4S&XRlFY!6bBA$(RBM_g&$Xs5Z0;rrE#r
-Qiu"?s.o&]Qil%As7ZDY"5NqVo)4pXi;`iGrg3rB7G%S*R$c5!rrVhrh#<ZClMpnGrg3cHWqlJj
-"R:fBEiSg4"4rp-jSf)YeGYd4rrT]tpAY'lc2O(5o;_ijao7Y5UAt8AQnilQV>gJp_Z#o6WW3"A
-fX$s4XT/=@Qm7?QYl=Y&\GhiqZi0n).e<H9!Tl<;rrLq?JcC<$a8^Y~>
-"s*`o]`1dPqYpS`K_59F2Wju<"1Ek"n,E=f]Rg'8%"b>U]S%>KKVAGGZ[r+/!J7HPrrEN]rr3:/
-_>j(QI_5WWK)UE/J\(kRdf9?VB)V`0*W,j<O`W_arrFipre(B(bl<e(KEcrfV>pSV3;idVL])l/
-J(ai;IK"m%Ibk$RrIb9%ir4?(KEH\cqL&9q#C[iJs6,,1M#RDUiu<IHKEHYom!\kd!e,arq>UTZ
-XT*=@p&>-?KJL1=rrL`$rIb0.rVm'u!9sO`c@>hH"FQ[<aajAD%"joHab23XKTuN:_1;N<'S<"X
-IS>?HKS$$"]n@GLKV8AFZ[r+/!J7HQrrFV?qYpTY2Z*LTh*6JjJcEdjJ,~>
-"s*`o]`1dPqYpS`K_59F2Wju<"1Ek"n,E=f]Rg'8%"b>U]S%>KKVAGGZ[r+/!J7HPrrEN]rr3:/
-_>j(QI_5WWK)UE/J\(kRdf9?VB)V`0*W,j<O`W_arrFipre(B(bl<e(KEcrfV>pSV3;idVL])l/
-J(ai;IK"m%Ibk$RrIb9%ir4?(KEH\cqL&9q#C[iJs6,,1M#RDUiu<IHKEHYom!\kd!e,arq>UTZ
-XT*=@p&>-?KJL1=rrL`$rIb0.rVm'u!9sO`c@>hH"FQ[<aajAD%"joHab23XKTuN:_1;N<'S<"X
-IS>?HKS$$"]n@GLKV8AFZ[r+/!J7HQrrFV?qYpTY2Z*LTh*6JjJcEdjJ,~>
-"s*`o]`1dPqYpS`K_59F2Wju<"1Ek"n,E=f]Rg'8%"b>U]S%>KKVAGGZ[r+/!J7HPrrEN]rr3:/
-_>j(QI_5WWK)UE/J\(kRdf9?VB)V`0*W,j<O`W_arrFipre(B(bl<e(KEcrfV>pSV3;idVL])l/
-J(ai;IK"m%Ibk$RrIb9%ir4?(KEH\cqL&9q#C[iJs6,,1M#RDUiu<IHKEHYom!\kd!e,arq>UTZ
-XT*=@p&>-?KJL1=rrL`$rIb0.rVm'u!9sO`c@>hH"FQ[<aajAD%"joHab23XKTuN:_1;N<'S<"X
-IS>?HKS$$"]n@GLKV8AFZ[r+/!J7HQrrFV?qYpTY2Z*LTh*6JjJcEdjJ,~>
-!$2%<!Dgu9rr=)3rrG%?qu6[Kn,E=fI@pN=!URQ"rrG1?rVln7Yl=Y'k/I<!!N!+$rs;oGF(M&\
-s8Q$?rr3M'HN-Ucs8TQ?s8Rm]$XStnrrM%?rVlmQR/[*pJ=QWfo`+sD9;V[gj>d);!$2%<"D>1C
-(pX)?"(&_A*W?!?_!:k?rVlsoch&XbrrU.ifDbdNP_f>=!okQBrr3'WkhAE&rrG^@p&>&5Wq65k
-@CuO=!O6J>rr=)<rs$32p](8dIK'6L*WQ/+L&V)Qk;N>>!E@/=rrIk?rr3;U8,n$Kk5YJ+:]C@p
-45p/<!H#%>rrM9#rr3!Ko(r@eju3,:!Sotks+13js*t~>
-!$2%<!Dgu9rr=)3rrG%?qu6[Kn,E=fI@pN=!URQ"rrG1?rVln7Yl=Y'k/I<!!N!+$rs;oGF(M&\
-s8Q$?rr3M'HN-Ucs8TQ?s8Rm]$XStnrrM%?rVlmQR/[*pJ=QWfo`+sD9;V[gj>d);!$2%<"D>1C
-(pX)?"(&_A*W?!?_!:k?rVlsoch&XbrrU.ifDbdNP_f>=!okQBrr3'WkhAE&rrG^@p&>&5Wq65k
-@CuO=!O6J>rr=)<rs$32p](8dIK'6L*WQ/+L&V)Qk;N>>!E@/=rrIk?rr3;U8,n$Kk5YJ+:]C@p
-45p/<!H#%>rrM9#rr3!Ko(r@eju3,:!Sotks+13js*t~>
-!$2%<!Dgu9rr=)3rrG%?qu6[Kn,E=fI@pN=!URQ"rrG1?rVln7Yl=Y'k/I<!!N!+$rs;oGF(M&\
-s8Q$?rr3M'HN-Ucs8TQ?s8Rm]$XStnrrM%?rVlmQR/[*pJ=QWfo`+sD9;V[gj>d);!$2%<"D>1C
-(pX)?"(&_A*W?!?_!:k?rVlsoch&XbrrU.ifDbdNP_f>=!okQBrr3'WkhAE&rrG^@p&>&5Wq65k
-@CuO=!O6J>rr=)<rs$32p](8dIK'6L*WQ/+L&V)Qk;N>>!E@/=rrIk?rr3;U8,n$Kk5YJ+:]C@p
-45p/<!H#%>rrM9#rr3!Ko(r@eju3,:!Sotks+13js*t~>
-!$2%<!Dgu:rrHN?o`"qMk55/Z/ar]=!T%ep5lbQrrrG1?rVloOB`:9tFSGe;>;EA"rVlms2#]cO
-.=2"ddf9?VB)hnV^)"H2r;QfU4T59\1$no>"G!$B..mN="aHmDs5Z0;rr<r85m&%6ruM(<"(&_A
-*W,j;r?)"<"&7,6./j/H7G%P=!L/E>rrM.?rVlsVkhAE&rrG^@p&>&5Wq65k@CuO=!O6J>rr=)7
-rrJd@rr3*As8SE0r]pQH2ZE^W<65%<!JZp>rrgnCs*gR=rrLA?rr3!\iVicWg1^IO!-A,=!@m[:
-rrM7?qu6]Q5Crics2Y.i~>
-!$2%<!Dgu:rrHN?o`"qMk55/Z/ar]=!T%ep5lbQrrrG1?rVloOB`:9tFSGe;>;EA"rVlms2#]cO
-.=2"ddf9?VB)hnV^)"H2r;QfU4T59\1$no>"G!$B..mN="aHmDs5Z0;rr<r85m&%6ruM(<"(&_A
-*W,j;r?)"<"&7,6./j/H7G%P=!L/E>rrM.?rVlsVkhAE&rrG^@p&>&5Wq65k@CuO=!O6J>rr=)7
-rrJd@rr3*As8SE0r]pQH2ZE^W<65%<!JZp>rrgnCs*gR=rrLA?rr3!\iVicWg1^IO!-A,=!@m[:
-rrM7?qu6]Q5Crics2Y.i~>
-!$2%<!Dgu:rrHN?o`"qMk55/Z/ar]=!T%ep5lbQrrrG1?rVloOB`:9tFSGe;>;EA"rVlms2#]cO
-.=2"ddf9?VB)hnV^)"H2r;QfU4T59\1$no>"G!$B..mN="aHmDs5Z0;rr<r85m&%6ruM(<"(&_A
-*W,j;r?)"<"&7,6./j/H7G%P=!L/E>rrM.?rVlsVkhAE&rrG^@p&>&5Wq65k@CuO=!O6J>rr=)7
-rrJd@rr3*As8SE0r]pQH2ZE^W<65%<!JZp>rrgnCs*gR=rrLA?rr3!\iVicWg1^IO!-A,=!@m[:
-rrM7?qu6]Q5Crics2Y.i~>
-!$2%<!Dgu;rrQWBrUg*j2Wjo:!A3d=rrD9^gB"`srr3![ir&fVk5O*9Wd+=="'_Wb48o0[;m$#Q
-#OMI_df9?VB)V`0*W#d:i&pu<!AWs?rrdkBs![O=rrmYDs8V.>r;Qa:r7_;GruM(<"(&_A*W,j;
-r?)"<"&7,6./j/H7G%P=!L/E>rrM.?rVlsVkk_C[,QXh=p&>&5Wq65k@CuO=!O6J>rr=)7rrMYA
-rZhWqs8SF+rS%>3rr3!uaSl,>L6hi="P-*CI\-Q=!R4F>rrG4?r;[email protected]<H9!Tl<;
-rrLq?JcC<$a8^Y~>
-!$2%<!Dgu;rrQWBrUg*j2Wjo:!A3d=rrD9^gB"`srr3![ir&fVk5O*9Wd+=="'_Wb48o0[;m$#Q
-#OMI_df9?VB)V`0*W#d:i&pu<!AWs?rrdkBs![O=rrmYDs8V.>r;Qa:r7_;GruM(<"(&_A*W,j;
-r?)"<"&7,6./j/H7G%P=!L/E>rrM.?rVlsVkk_C[,QXh=p&>&5Wq65k@CuO=!O6J>rr=)7rrMYA
-rZhWqs8SF+rS%>3rr3!uaSl,>L6hi="P-*CI\-Q=!R4F>rrG4?r;[email protected]<H9!Tl<;
-rrLq?JcC<$a8^Y~>
-!$2%<!Dgu;rrQWBrUg*j2Wjo:!A3d=rrD9^gB"`srr3![ir&fVk5O*9Wd+=="'_Wb48o0[;m$#Q
-#OMI_df9?VB)V`0*W#d:i&pu<!AWs?rrdkBs![O=rrmYDs8V.>r;Qa:r7_;GruM(<"(&_A*W,j;
-r?)"<"&7,6./j/H7G%P=!L/E>rrM.?rVlsVkk_C[,QXh=p&>&5Wq65k@CuO=!O6J>rr=)7rrMYA
-rZhWqs8SF+rS%>3rr3!uaSl,>L6hi="P-*CI\-Q=!R4F>rrG4?r;[email protected]<H9!Tl<;
-rrLq?JcC<$a8^Y~>
-%NYTElKUsRlL"WOoPM5>p&>0dl7pcSrr38pl71QUs8S%KrosO!?iL'19%*"9C]Ag_rosNhDZ0S9
-'/fdh$!Y7@i>l@us'`V?l3Qq[s&m;*`t`4brr=):rs7u:2sU&8s"Wm>rsjRLs#T-(lBDdTs8W)9
->5eI$0`C8=pAb.5rVlt+^Afhal2tM?r@e-7"'3nD2u`(NC^AYmqs&uclMCP@3W8s[2!Egmro*tA
-qu-O&IgEmjs82*HBq4JRrVlq:#grYO#l!UeX6T]a[r;61!&4BO#$)#ps8T-Jro+(Hs8SaFrosLM
-rVm+4]^!gBs,`ECl3YL3s*bTflKZ/krr33rdH\>Ys*h!Il2e2-rr3#p,l7NA,Ph9;!rFA@r;Qii
-#YfmMJcF'rJ,~>
-%NYTElKUsRlL"WOoPM5>p&>0dl7pcSrr38pl71QUs8S%KrosO!?iL'19%*"9C]Ag_rosNhDZ0S9
-'/fdh$!Y7@i>l@us'`V?l3Qq[s&m;*`t`4brr=):rs7u:2sU&8s"Wm>rsjRLs#T-(lBDdTs8W)9
->5eI$0`C8=pAb.5rVlt+^Afhal2tM?r@e-7"'3nD2u`(NC^AYmqs&uclMCP@3W8s[2!Egmro*tA
-qu-O&IgEmjs82*HBq4JRrVlq:#grYO#l!UeX6T]a[r;61!&4BO#$)#ps8T-Jro+(Hs8SaFrosLM
-rVm+4]^!gBs,`ECl3YL3s*bTflKZ/krr33rdH\>Ys*h!Il2e2-rr3#p,l7NA,Ph9;!rFA@r;Qii
-#YfmMJcF'rJ,~>
-%NYTElKUsRlL"WOoPM5>p&>0dl7pcSrr38pl71QUs8S%KrosO!?iL'19%*"9C]Ag_rosNhDZ0S9
-'/fdh$!Y7@i>l@us'`V?l3Qq[s&m;*`t`4brr=):rs7u:2sU&8s"Wm>rsjRLs#T-(lBDdTs8W)9
->5eI$0`C8=pAb.5rVlt+^Afhal2tM?r@e-7"'3nD2u`(NC^AYmqs&uclMCP@3W8s[2!Egmro*tA
-qu-O&IgEmjs82*HBq4JRrVlq:#grYO#l!UeX6T]a[r;61!&4BO#$)#ps8T-Jro+(Hs8SaFrosLM
-rVm+4]^!gBs,`ECl3YL3s*bTflKZ/krr33rdH\>Ys*h!Il2e2-rr3#p,l7NA,Ph9;!rFA@r;Qii
-#YfmMJcF'rJ,~>
-!Zh<Nr%\CPs8SOkoD\fMr\=IJrr2tQr\=IQrr2tJr\=IXr;Qgi11L7_!-.un!,;B2!BaK`rrIJk
-rr3,5NrT,br\=J%rr3+%10(eqrVljiqu6Xfr\=V=s8Q6jrr3:mYlF_b1,=WJ\,QC/dUqP=rrDoo
-1'=ZYs%<7i"+JGnmJSdB])VfmrA"Jks8V!U1'FgqhuD@-1'>l&l!XJi"'k6gV>W.MZMa_%"dK_8
-s8UXI1&s31rrRrdd/O%FYPg3Yp](8mrA"BPrVm(C1@>,Am",-k"?b98s-3L<!(Qnd!a[WVrr2tR
-r\=aXs8RP>BJM>Hr;Qgj11C1^!-8&o!,2<1!CkZ<rrLS?qu6]C:&FqloeL<6s+13rs*t~>
-!Zh<Nr%\CPs8SOkoD\fMr\=IJrr2tQr\=IQrr2tJr\=IXr;Qgi11L7_!-.un!,;B2!BaK`rrIJk
-rr3,5NrT,br\=J%rr3+%10(eqrVljiqu6Xfr\=V=s8Q6jrr3:mYlF_b1,=WJ\,QC/dUqP=rrDoo
-1'=ZYs%<7i"+JGnmJSdB])VfmrA"Jks8V!U1'FgqhuD@-1'>l&l!XJi"'k6gV>W.MZMa_%"dK_8
-s8UXI1&s31rrRrdd/O%FYPg3Yp](8mrA"BPrVm(C1@>,Am",-k"?b98s-3L<!(Qnd!a[WVrr2tR
-r\=aXs8RP>BJM>Hr;Qgj11C1^!-8&o!,2<1!CkZ<rrLS?qu6]C:&FqloeL<6s+13rs*t~>
-!Zh<Nr%\CPs8SOkoD\fMr\=IJrr2tQr\=IQrr2tJr\=IXr;Qgi11L7_!-.un!,;B2!BaK`rrIJk
-rr3,5NrT,br\=J%rr3+%10(eqrVljiqu6Xfr\=V=s8Q6jrr3:mYlF_b1,=WJ\,QC/dUqP=rrDoo
-1'=ZYs%<7i"+JGnmJSdB])VfmrA"Jks8V!U1'FgqhuD@-1'>l&l!XJi"'k6gV>W.MZMa_%"dK_8
-s8UXI1&s31rrRrdd/O%FYPg3Yp](8mrA"BPrVm(C1@>,Am",-k"?b98s-3L<!(Qnd!a[WVrr2tR
-r\=aXs8RP>BJM>Hr;Qgj11C1^!-8&o!,2<1!CkZ<rrLS?qu6]C:&FqloeL<6s+13rs*t~>
-!$/$<"ip05s0lUqrrL'0a8Z1p62gfa/+NT<!F<J3rrGj@kPkRUIK'6Imk*c'!IgX(rrMb1r;Qe0
-r;6Ko@tFZ2s2G"g~>
-!$/$<"ip05s0lUqrrL'0a8Z1p62gfa/+NT<!F<J3rrGj@kPkRUIK'6Imk*c'!IgX(rrMb1r;Qe0
-r;6Ko@tFZ2s2G"g~>
-!$/$<"ip05s0lUqrrL'0a8Z1p62gfa/+NT<!F<J3rrGj@kPkRUIK'6Imk*c'!IgX(rrMb1r;Qe0
-r;6Ko@tFZ2s2G"g~>
-!$/$<"db13PDH-0rrMD.rK@8'p\t0oa*QJ3rrTu\jQHODaFF2Q!Ki-#rrIS?JcC<$SH"*~>
-!$/$<"db13PDH-0rrMD.rK@8'p\t0oa*QJ3rrTu\jQHODaFF2Q!Ki-#rrIS?JcC<$SH"*~>
-!$/$<"db13PDH-0rrMD.rK@8'p\t0oa*QJ3rrTu\jQHODaFF2Q!Ki-#rrIS?JcC<$SH"*~>
-!$/!;".k@+Wh04jiVeT5li$ha_US2W!P7(JrrC%;M#`Y#rrL$cJcC<$SH"*~>
-!$/!;".k@+Wh04jiVeT5li$ha_US2W!P7(JrrC%;M#`Y#rrL$cJcC<$SH"*~>
-!$/!;".k@+Wh04jiVeT5li$ha_US2W!P7(JrrC%;M#`Y#rrL$cJcC<$SH"*~>
-!$2";!d\!iJc>iPBN]t=s+13$s,R,0~>
-!$2";!d\!iJc>iPBN]t=s+13$s,R,0~>
-!$2";!d\!iJc>iPBN]t=s+13$s,R,0~>
-!$2%<"*pi_bhN-ufQmJr!GFXFrrGGskl1[N](l:-aMX^)JcC<$JcCf2J,~>
-!$2%<"*pi_bhN-ufQmJr!GFXFrrGGskl1[N](l:-aMX^)JcC<$JcCf2J,~>
-!$2%<"*pi_bhN-ufQmJr!GFXFrrGGskl1[N](l:-aMX^)JcC<$JcCf2J,~>
-!$2%<!DgtnrrL>?rr3#^i7%],i9'8'!I1I7rrKi?JcC<$JcCf2J,~>
-!$2%<!DgtnrrL>?rr3#^i7%],i9'8'!I1I7rrKi?JcC<$JcCf2J,~>
-!$2%<!DgtnrrL>?rr3#^i7%],i9'8'!I1I7rrKi?JcC<$JcCf2J,~>
-!$2%<!b/kArr2uhroFFJs8V`^mcEQnrr2ufroF.Drr2ueroF.Err3>ojlP[L;#gR`jlQI@"n;9O
-jlPk.rrqcNjluO/q#:fjq>^Kimf3=RqW?o$n,E=gkiM+-rrD9^jT+iMrrD6]jT+lNrs.]Jjm[Mk
-s8W&Z!;-9j!rK6?JcC<$JcCf2J,~>
-!$2%<!b/kArr2uhroFFJs8V`^mcEQnrr2ufroF.Drr2ueroF.Err3>ojlP[L;#gR`jlQI@"n;9O
-jlPk.rrqcNjluO/q#:fjq>^Kimf3=RqW?o$n,E=gkiM+-rrD9^jT+iMrrD6]jT+lNrs.]Jjm[Mk
-s8W&Z!;-9j!rK6?JcC<$JcCf2J,~>
-!$2%<!b/kArr2uhroFFJs8V`^mcEQnrr2ufroF.Drr2ueroF.Err3>ojlP[L;#gR`jlQI@"n;9O
-jlPk.rrqcNjluO/q#:fjq>^Kimf3=RqW?o$n,E=gkiM+-rrD9^jT+iMrrD6]jT+lNrs.]Jjm[Mk
-s8W&Z!;-9j!rK6?JcC<$JcCf2J,~>
-!$2(=#N*U%n,NFQJc7S:6.5e!BkoXd7b%J#GQ'N(9%Et'ErJ!-:Y5X,D)XC@TMY[gHoD</rsik&
-;`?XAh>c;<2`FX*MYR2b;p,.?^Kpm>8u4d32f[pYs&:a0rVloJ8,bFMHKbCW6N/nPJ*R'\4Z><@
-?D[\J3W:rBM=(?Cj'9[bJcC<$JcCi3J,~>
-!$2(=#N*U%n,NFQJc7S:6.5e!BkoXd7b%J#GQ'N(9%Et'ErJ!-:Y5X,D)XC@TMY[gHoD</rsik&
-;`?XAh>c;<2`FX*MYR2b;p,.?^Kpm>8u4d32f[pYs&:a0rVloJ8,bFMHKbCW6N/nPJ*R'\4Z><@
-?D[\J3W:rBM=(?Cj'9[bJcC<$JcCi3J,~>
-!$2(=#N*U%n,NFQJc7S:6.5e!BkoXd7b%J#GQ'N(9%Et'ErJ!-:Y5X,D)XC@TMY[gHoD</rsik&
-;`?XAh>c;<2`FX*MYR2b;p,.?^Kpm>8u4d32f[pYs&:a0rVloJ8,bFMHKbCW6N/nPJ*R'\4Z><@
-?D[\J3W:rBM=(?Cj'9[bJcC<$JcCi3J,~>
-!$2(=!c7q^rr3"kIfB?UmOnO*/AhGeju<=#NrK%]k^NPcQi@!keO]^gTE"r]6W!a]!$2%<%;\)^
-s8T]>s'rV>s3OI6rshuMs8Ti>s8P\[p&G&[KDtlOkqi;<!BK3>rrfR8s"Wm>rsXFJs![O>s0sGQ
-ruh:>rrI&?rr3&6!.0:sJcC<$OT0h~>
-!$2(=!c7q^rr3"kIfB?UmOnO*/AhGeju<=#NrK%]k^NPcQi@!keO]^gTE"r]6W!a]!$2%<%;\)^
-s8T]>s'rV>s3OI6rshuMs8Ti>s8P\[p&G&[KDtlOkqi;<!BK3>rrfR8s"Wm>rsXFJs![O>s0sGQ
-ruh:>rrI&?rr3&6!.0:sJcC<$OT0h~>
-!$2(=!c7q^rr3"kIfB?UmOnO*/AhGeju<=#NrK%]k^NPcQi@!keO]^gTE"r]6W!a]!$2%<%;\)^
-s8T]>s'rV>s3OI6rshuMs8Ti>s8P\[p&G&[KDtlOkqi;<!BK3>rrfR8s"Wm>rsXFJs![O>s0sGQ
-ruh:>rrI&?rr3&6!.0:sJcC<$OT0h~>
-!$2(=#Hi'&pAb/b7fJDNKeECkLAq2Uju<=#Nr/hWKpVf="P$'CI@pN=!R+C=rr=)<rrHr?rr389
-@K0iJs8UG>p\tOub5_LV?2spsdf07IR=kM=!U2E=rrG.?qu6[Om/I"fJ=QWfo`"jnGbtE_NW+qC
-5-=kbmtYnkJcC<$JcCi3J,~>
-!$2(=#Hi'&pAb/b7fJDNKeECkLAq2Uju<=#Nr/hWKpVf="P$'CI@pN=!R+C=rr=)<rrHr?rr389
-@K0iJs8UG>p\tOub5_LV?2spsdf07IR=kM=!U2E=rrG.?qu6[Om/I"fJ=QWfo`"jnGbtE_NW+qC
-5-=kbmtYnkJcC<$JcCi3J,~>
-!$2(=#Hi'&pAb/b7fJDNKeECkLAq2Uju<=#Nr/hWKpVf="P$'CI@pN=!R+C=rr=)<rrHr?rr389
-@K0iJs8UG>p\tOub5_LV?2spsdf07IR=kM=!U2E=rrG.?qu6[Om/I"fJ=QWfo`"jnGbtE_NW+qC
-5-=kbmtYnkJcC<$JcCi3J,~>
-!$2%<#+^SDs8S]\rJguSs-AE=rrhICs,N-:rrIh?rr3,O8H4+1rr3#C;#UCo*W?!=Cp<p=#eOOF
-\p8:8G-L`@#uf"Hs1_k>s%:`=rrJO?rr3#`1]@=S3TL#:!AWs?rrdkBs![O=rrdSCrud="NWn2;
-s6k`>JcC<$JcCf2J,~>
-!$2%<#+^SDs8S]\rJguSs-AE=rrhICs,N-:rrIh?rr3,O8H4+1rr3#C;#UCo*W?!=Cp<p=#eOOF
-\p8:8G-L`@#uf"Hs1_k>s%:`=rrJO?rr3#`1]@=S3TL#:!AWs?rrdkBs![O=rrdSCrud="NWn2;
-s6k`>JcC<$JcCf2J,~>
-!$2%<#+^SDs8S]\rJguSs-AE=rrhICs,N-:rrIh?rr3,O8H4+1rr3#C;#UCo*W?!=Cp<p=#eOOF
-\p8:8G-L`@#uf"Hs1_k>s%:`=rrJO?rr3#`1]@=S3TL#:!AWs?rrdkBs![O=rrdSCrud="NWn2;
-s6k`>JcC<$JcCf2J,~>
-!$2%<!Dgu>rrJa@qu6\_LAq2Uju<=#NrK%]k^NPcQi@!keO]^gTE"r]6W!a]!$2%<!Go">rs-/E
-s-JqMX1J3.!EOLFrs;WHs8Ti>s8P^>rr3"eKDtlOkqi;<!BK3>rrfR8s"Wm>rsXFJs![O>s0sGQ
-ruh:9rrKi?JcC<$JcCf2J,~>
-!$2%<!Dgu>rrJa@qu6\_LAq2Uju<=#NrK%]k^NPcQi@!keO]^gTE"r]6W!a]!$2%<!Go">rs-/E
-s-JqMX1J3.!EOLFrs;WHs8Ti>s8P^>rr3"eKDtlOkqi;<!BK3>rrfR8s"Wm>rsXFJs![O>s0sGQ
-ruh:9rrKi?JcC<$JcCf2J,~>
-!$2%<!Dgu>rrJa@qu6\_LAq2Uju<=#NrK%]k^NPcQi@!keO]^gTE"r]6W!a]!$2%<!Go">rs-/E
-s-JqMX1J3.!EOLFrs;WHs8Ti>s8P^>rr3"eKDtlOkqi;<!BK3>rrfR8s"Wm>rsXFJs![O>s0sGQ
-ruh:9rrKi?JcC<$JcCf2J,~>
-!$2%<!Dgu>rrMD9r\jsKs8SC>rr3,`2ui#ar\jsPec4`Or\kNefDjlJ2`F*s;#gQC2[23Qs8Qo>
-rr3,[email protected]\jgur;Qd"2u`g`g/U'j>EbER9%*_=%%2bJs&:`]2i[k;e49Ks"FB;3dR*pl%"IRB
-coj<HF'b^CcT1t`!3#kr!PVlks+13$s,[21~>
-!$2%<!Dgu>rrMD9r\jsKs8SC>rr3,`2ui#ar\jsPec4`Or\kNefDjlJ2`F*s;#gQC2[23Qs8Qo>
-rr3,[email protected]\jgur;Qd"2u`g`g/U'j>EbER9%*_=%%2bJs&:`]2i[k;e49Ks"FB;3dR*pl%"IRB
-coj<HF'b^CcT1t`!3#kr!PVlks+13$s,[21~>
-!$2%<!Dgu>rrMD9r\jsKs8SC>rr3,`2ui#ar\jsPec4`Or\kNefDjlJ2`F*s;#gQC2[23Qs8Qo>
-rr3,[email protected]\jgur;Qd"2u`g`g/U'j>EbER9%*_=%%2bJs&:`]2i[k;e49Ks"FB;3dR*pl%"IRB
-coj<HF'b^CcT1t`!3#kr!PVlks+13$s,[21~>
-!$2%<#44f!56(ZRroF:Fs8V`^rr3-!lMpnRroF.Drr2ueroF.Err38mjlP\%mJm4SroF:Ks8VT_
-rr3,rn,IL3roF0ZH2[aDc8Y_%#jUO5lh0fJm/$_]"SD9bs60ID!:^!f!9jFD!:g'g!9a@C!:p-h
-#Nk.0nF?5Ps8D$`o`+qH*Dc*Ss+13$s,[21~>
-!$2%<#44f!56(ZRroF:Fs8V`^rr3-!lMpnRroF.Drr2ueroF.Err38mjlP\%mJm4SroF:Ks8VT_
-rr3,rn,IL3roF0ZH2[aDc8Y_%#jUO5lh0fJm/$_]"SD9bs60ID!:^!f!9jFD!:g'g!9a@C!:p-h
-#Nk.0nF?5Ps8D$`o`+qH*Dc*Ss+13$s,[21~>
-!$2%<#44f!56(ZRroF:Fs8V`^rr3-!lMpnRroF.Drr2ueroF.Err38mjlP\%mJm4SroF:Ks8VT_
-rr3,rn,IL3roF0ZH2[aDc8Y_%#jUO5lh0fJm/$_]"SD9bs60ID!:^!f!9jFD!:g'g!9a@C!:p-h
-#Nk.0nF?5Ps8D$`o`+qH*Dc*Ss+13$s,[21~>
-!$/lT!I(UDhuT^&rVloB:kAXts+13$s3Udr~>
-!$/lT!I(UDhuT^&rVloB:kAXts+13$s3Udr~>
-!$/lT!I(UDhuT^&rVloB:kAXts+13$s3Udr~>
-!$/iS!-8'$!-\;?!)nIKJcC<$JcF'rJ,~>
-!$/iS!-8'$!-\;?!)nIKJcC<$JcF'rJ,~>
-!$/iS!-8'$!-\;?!)nIKJcC<$JcF'rJ,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-"!.FAao7+sNW/qY`R48V"0^kcRDo1.QN,gOJcC<$JcC<$iW"E~>
-"!.FAao7+sNW/qY`R48V"0^kcRDo1.QN,gOJcC<$JcC<$iW"E~>
-"!.FAao7+sNW/qY`R48V"0^kcRDo1.QN,gOJcC<$JcC<$iW"E~>
-"!.EcIf>N8P(N`6b'V_2rrZ3AqBEoY"!.ENAqBu5s+13$s5F!.~>
-"!.EcIf>N8P(N`6b'V_2rrZ3AqBEoY"!.ENAqBu5s+13$s5F!.~>
-"!.EcIf>N8P(N`6b'V_2rrZ3AqBEoY"!.ENAqBu5s+13$s5F!.~>
-"!.E>FoMCApEon>!mbW@o`#"land4#rrX;A[q:3kJcC<$JcF^/J,~>
-"!.E>FoMCApEon>!mbW@o`#"land4#rrX;A[q:3kJcC<$JcF^/J,~>
-"!.E>FoMCApEon>!mbW@o`#"land4#rrX;A[q:3kJcC<$JcF^/J,~>
-"!.F0jSo/[8C[V<!o$B@p&>9Qo`!>>s.-4irrh.os-Btirrgnos,aejrs6qrs,"Pks57Vjrr?j6
-1&u7krrYqM13WZs!+#RZ!.FhG"4R;?iIV#[s+13$s5F!.~>
-"!.F0jSo/[8C[V<!o$B@p&>9Qo`!>>s.-4irrh.os-Btirrgnos,aejrs6qrs,"Pks57Vjrr?j6
-1&u7krrYqM13WZs!+#RZ!.FhG"4R;?iIV#[s+13$s5F!.~>
-"!.F0jSo/[8C[V<!o$B@p&>9Qo`!>>s.-4irrh.os-Btirrgnos,aejrs6qrs,"Pks57Vjrr?j6
-1&u7krrYqM13WZs!+#RZ!.FhG"4R;?iIV#[s+13$s5F!.~>
-!$2%<!r>IAqu6]a0CSoAKpVf="P$'CI@pN='[0DRFK#6>hA08oCp<s>fgPl?E3K9+!NL>Brs'\0
-[oNJ.@D2[*!M"jps+13$s+14(s*t~>
-!$2%<!r>IAqu6]a0CSoAKpVf="P$'CI@pN='[0DRFK#6>hA08oCp<s>fgPl?E3K9+!NL>Brs'\0
-[oNJ.@D2[*!M"jps+13$s+14(s*t~>
-!$2%<!r>IAqu6]a0CSoAKpVf="P$'CI@pN='[0DRFK#6>hA08oCp<s>fgPl?E3K9+!NL>Brs'\0
-[oNJ.@D2[*!M"jps+13$s+14(s*t~>
-!$2(=!pX(@qYpTT4R`:NKpVf="P$'CI>RsX'X(@5FK#5r5/^V(Cp<s>fgPl?A%DU=!OHM>rs'\E
-aAr9?;m$&R!K28Ts+13$s+14(s*t~>
-!$2(=!pX(@qYpTT4R`:NKpVf="P$'CI>RsX'X(@5FK#5r5/^V(Cp<s>fgPl?A%DU=!OHM>rs'\E
-aAr9?;m$&R!K28Ts+13$s+14(s*t~>
-!$2(=!pX(@qYpTT4R`:NKpVf="P$'CI>RsX'X(@5FK#5r5/^V(Cp<s>fgPl?A%DU=!OHM>rs'\E
-aAr9?;m$&R!K28Ts+13$s+14(s*t~>
-"WdXCiHE09rrUPJp@&"^KpVf="P$'CI4>.]'JrYdFK!D[s28(?Cp<s>fgPl?A%DU=%'s[Js34F>
-aAr9?;`+G=!1\W?JcC<$JcFI(J,~>
-"WdXCiHE09rrUPJp@&"^KpVf="P$'CI4>.]'JrYdFK!D[s28(?Cp<s>fgPl?A%DU=%'s[Js34F>
-aAr9?;`+G=!1\W?JcC<$JcFI(J,~>
-"WdXCiHE09rrUPJp@&"^KpVf="P$'CI4>.]'JrYdFK!D[s28(?Cp<s>fgPl?A%DU=%'s[Js34F>
-aAr9?;`+G=!1\W?JcC<$JcFI(J,~>
-"<IO"K"LmZ!lf6Amf*TIQiI*^L.M>mTDnj)bY\=]C2NA<`**+VYlFaV70!9s\c2U;ZYBI>52ZC]
-<WE(tb45K5pS#?Qs+13$s+146s*t~>
-"<IO"K"LmZ!lf6Amf*TIQiI*^L.M>mTDnj)bY\=]C2NA<`**+VYlFaV70!9s\c2U;ZYBI>52ZC]
-<WE(tb45K5pS#?Qs+13$s+146s*t~>
-"<IO"K"LmZ!lf6Amf*TIQiI*^L.M>mTDnj)bY\=]C2NA<`**+VYlFaV70!9s\c2U;ZYBI>52ZC]
-<WE(tb45K5pS#?Qs+13$s+146s*t~>
-"!.E>4oL$;QN.!%J(j;i$,D(EKS*o.s*^O=rtN[Rs)_,ss8U#?s(knmKQ&0Bs0%"QKFEF;s0*Ve
-KP)jJs/(DIKE/:MrrVEb;1\aus+13$s60K5~>
-"!.E>4oL$;QN.!%J(j;i$,D(EKS*o.s*^O=rtN[Rs)_,ss8U#?s(knmKQ&0Bs0%"QKFEF;s0*Ve
-KP)jJs/(DIKE/:MrrVEb;1\aus+13$s60K5~>
-"!.E>4oL$;QN.!%J(j;i$,D(EKS*o.s*^O=rtN[Rs)_,ss8U#?s(knmKQ&0Bs0%"QKFEF;s0*Ve
-KP)jJs/(DIKE/:MrrVEb;1\aus+13$s60K5~>
-!Zh<rr0RVbs8U<pli.7-R$aGp8H6ibrr3,d\GsV)rr3)`]`5qKQiqA:s8TJ*Qisnus''RDQiq#A
-s8T8$QiOknrrVn]\Ujd3s+13$s60K5~>
-!Zh<rr0RVbs8U<pli.7-R$aGp8H6ibrr3,d\GsV)rr3)`]`5qKQiqA:s8TJ*Qisnus''RDQiq#A
-s8T8$QiOknrrVn]\Ujd3s+13$s60K5~>
-!Zh<rr0RVbs8U<pli.7-R$aGp8H6ibrr3,d\GsV)rr3)`]`5qKQiqA:s8TJ*Qisnus''RDQiq#A
-s8T8$QiOknrrVn]\Ujd3s+13$s60K5~>
-!$1"t!NEL+rrLY@li.!t@JKj'cgC`3!Tqsas+13$s+13us*t~>
-!$1"t!NEL+rrLY@li.!t@JKj'cgC`3!Tqsas+13$s+13us*t~>
-!$1"t!NEL+rrLY@li.!t@JKj'cgC`3!Tqsas+13$s+13us*t~>
-!$1"t!U4S&/HJH"li."Wj+75]s+13$s2+ed~>
-!$1"t!U4S&/HJH"li."Wj+75]s+13$s2+ed~>
-!$1"t!U4S&/HJH"li."Wj+75]s+13$s2+ed~>
-!$2(="8MHXoB-&Qp&=C[nU^_$rr`#do(.G4JcDABJ,~>
-!$2(="8MHXoB-&Qp&=C[nU^_$rr`#do(.G4JcDABJ,~>
-!$2(="8MHXoB-&Qp&=C[nU^_$rr`#do(.G4JcDABJ,~>
-!$2(=")T&-1&V%PiV<?N"6A%arr2otkl0-5g\h'Ph>HmE!8@>M!oDM`r;QiRf%p?*!9F(/!9j.V
-!WCjOrrUg'j8ArWec=e0rr`5Nf&cQ(!VYROrr`)Jf'<87!<)lI!:]mc!U0(HrrMTRr;Qlif%0?h
-rr_fBf(/e>!:^!=!;Q6e!U0(Ors%i@f(]4Eo_d8?g&D!Ol2K9+rrM*Rr;Qu_f%0j#s6]a8!oX+E
-r72)2s8RBo.2IL7JcDABJ,~>
-!$2(=")T&-1&V%PiV<?N"6A%arr2otkl0-5g\h'Ph>HmE!8@>M!oDM`r;QiRf%p?*!9F(/!9j.V
-!WCjOrrUg'j8ArWec=e0rr`5Nf&cQ(!VYROrr`)Jf'<87!<)lI!:]mc!U0(HrrMTRr;Qlif%0?h
-rr_fBf(/e>!:^!=!;Q6e!U0(Ors%i@f(]4Eo_d8?g&D!Ol2K9+rrM*Rr;Qu_f%0j#s6]a8!oX+E
-r72)2s8RBo.2IL7JcDABJ,~>
-!$2(=")T&-1&V%PiV<?N"6A%arr2otkl0-5g\h'Ph>HmE!8@>M!oDM`r;QiRf%p?*!9F(/!9j.V
-!WCjOrrUg'j8ArWec=e0rr`5Nf&cQ(!VYROrr`)Jf'<87!<)lI!:]mc!U0(HrrMTRr;Qlif%0?h
-rr_fBf(/e>!:^!=!;Q6e!U0(Ors%i@f(]4Eo_d8?g&D!Ol2K9+rrM*Rr;Qu_f%0j#s6]a8!oX+E
-r72)2s8RBo.2IL7JcDABJ,~>
-!$2(=!H#(<rrU\+ec#LRg2BGM^An5kH2^86<m(FA!mMnWo`"s6(&\(7c<Nh@bPqMIbZRD>cN!oK
-2>ouERJ-X]ZRbtR"N*i$CY/Rc"MdJrDV>$h"M.&lEnpBg!r.jWrVm0%WCB@+j8].frC-gJmJ[%d
-i)?WKrrVP,JGoK[ns2a7ORE/Kmug.0Pk"eRm>h08!9!SN!oR"WrVm,bK18>*qZ"e;7KaM,s5A>(
-7KEG]rrU_-eG]CPg2KMN^&S,8rC-lP56%S[7KGS@r;Qa;JcC<$TDsE~>
-!$2(=!H#(<rrU\+ec#LRg2BGM^An5kH2^86<m(FA!mMnWo`"s6(&\(7c<Nh@bPqMIbZRD>cN!oK
-2>ouERJ-X]ZRbtR"N*i$CY/Rc"MdJrDV>$h"M.&lEnpBg!r.jWrVm0%WCB@+j8].frC-gJmJ[%d
-i)?WKrrVP,JGoK[ns2a7ORE/Kmug.0Pk"eRm>h08!9!SN!oR"WrVm,bK18>*qZ"e;7KaM,s5A>(
-7KEG]rrU_-eG]CPg2KMN^&S,8rC-lP56%S[7KGS@r;Qa;JcC<$TDsE~>
-!$2(=!H#(<rrU\+ec#LRg2BGM^An5kH2^86<m(FA!mMnWo`"s6(&\(7c<Nh@bPqMIbZRD>cN!oK
-2>ouERJ-X]ZRbtR"N*i$CY/Rc"MdJrDV>$h"M.&lEnpBg!r.jWrVm0%WCB@+j8].frC-gJmJ[%d
-i)?WKrrVP,JGoK[ns2a7ORE/Kmug.0Pk"eRm>h08!9!SN!oR"WrVm,bK18>*qZ"e;7KaM,s5A>(
-7KEG]rrU_-eG]CPg2KMN^&S,8rC-lP56%S[7KGS@r;Qa;JcC<$TDsE~>
-!$2(=!H#(=rr^Pl*7b&g$.aRGs8Ql>s,N-=rs.@Es8U#Z'(>Mn!krU^rVmJLFlEAaEl.jnF6<M^
-FN+8a_=IU-X^NaYrt`"Xqu=rhdf6Ufs8U/hec2gjs8Tudg%YLJQVCKYrs5BFs8TH[ir:%trrHH?
-rr3)XK.X(srr__K4b3P3')7TQs8SOJoCS*2s8S@Gp@4-5oD\pMK.O&%rs%YBXT/<NSGW<iX)\0u
-KX^RQ"4)95eGfIPf7(a>s(nt<rrW1aM>[ATqNHs;rr='js+13Bs*t~>
-!$2(=!H#(=rr^Pl*7b&g$.aRGs8Ql>s,N-=rs.@Es8U#Z'(>Mn!krU^rVmJLFlEAaEl.jnF6<M^
-FN+8a_=IU-X^NaYrt`"Xqu=rhdf6Ufs8U/hec2gjs8Tudg%YLJQVCKYrs5BFs8TH[ir:%trrHH?
-rr3)XK.X(srr__K4b3P3')7TQs8SOJoCS*2s8S@Gp@4-5oD\pMK.O&%rs%YBXT/<NSGW<iX)\0u
-KX^RQ"4)95eGfIPf7(a>s(nt<rrW1aM>[ATqNHs;rr='js+13Bs*t~>
-!$2(=!H#(=rr^Pl*7b&g$.aRGs8Ql>s,N-=rs.@Es8U#Z'(>Mn!krU^rVmJLFlEAaEl.jnF6<M^
-FN+8a_=IU-X^NaYrt`"Xqu=rhdf6Ufs8U/hec2gjs8Tudg%YLJQVCKYrs5BFs8TH[ir:%trrHH?
-rr3)XK.X(srr__K4b3P3')7TQs8SOJoCS*2s8S@Gp@4-5oD\pMK.O&%rs%YBXT/<NSGW<iX)\0u
-KX^RQ"4)95eGfIPf7(a>s(nt<rrW1aM>[ATqNHs;rr='js+13Bs*t~>
-!$2(=!H#(>rrgYtbt$=`rrJF?rr3,`2uenurr35Z5QATNg+Dderr]f^iZ8!t!Go">rt)eNs0@.>
-s6"m>s'*=#It+Hlrr]'Il7;i5!CGQ?rsY$Js.+]?s3cD>s"Wm>rrIY?q#:GWNQ5&trr=)<rrZoB
-ruM(<#[Y7Fs5ea>F/es7"T!VCSUg_>!UMN=rsLsInURY>s/:J?gHkH2"QY'BEiT-=!Q&(>rr=):
-rra_Bs06D3rrgYtbt-@`rrJI?rr3#^2Z3RUq]Yk:!V7c;rr='js+13Bs*t~>
-!$2(=!H#(>rrgYtbt$=`rrJF?rr3,`2uenurr35Z5QATNg+Dderr]f^iZ8!t!Go">rt)eNs0@.>
-s6"m>s'*=#It+Hlrr]'Il7;i5!CGQ?rsY$Js.+]?s3cD>s"Wm>rrIY?q#:GWNQ5&trr=)<rrZoB
-ruM(<#[Y7Fs5ea>F/es7"T!VCSUg_>!UMN=rsLsInURY>s/:J?gHkH2"QY'BEiT-=!Q&(>rr=):
-rra_Bs06D3rrgYtbt-@`rrJI?rr3#^2Z3RUq]Yk:!V7c;rr='js+13Bs*t~>
-!$2(=!H#(>rrgYtbt$=`rrJF?rr3,`2uenurr35Z5QATNg+Dderr]f^iZ8!t!Go">rt)eNs0@.>
-s6"m>s'*=#It+Hlrr]'Il7;i5!CGQ?rsY$Js.+]?s3cD>s"Wm>rrIY?q#:GWNQ5&trr=)<rrZoB
-ruM(<#[Y7Fs5ea>F/es7"T!VCSUg_>!UMN=rsLsInURY>s/:J?gHkH2"QY'BEiT-=!Q&(>rr=):
-rra_Bs06D3rrgYtbt-@`rrJI?rr3#^2Z3RUq]Yk:!V7c;rr='js+13Bs*t~>
-!$2(=!H#(>rrh'#s$tW=rrJF?rr3Mk2uenus8W!s5QB*^s"3^5rr^F#ruM(<!Go">rt2kOs8TTE
-@Vr^Vs'&*]SXkV9q#:H,mdVh+rrGI@rr3ChMuWgT@UaQ)s8Oh?rr3"LSG<*dWW'q<rVlj<rVlt4
-[f7BIrs>hR^Am_@]`3&Pq#:KoXT+iArr3#c0`D"[4Q-8(M.0qOli5^*`Vs<HjS8`Xlb3==WrE#!
-_H[!=!$2";#)nfDs06C@raGm,q#:KNc2U>arr3"cL&V)Qk;N8<!HY:<rrI&?qu6X:JcC<$TDsE~>
-!$2(=!H#(>rrh'#s$tW=rrJF?rr3Mk2uenus8W!s5QB*^s"3^5rr^F#ruM(<!Go">rt2kOs8TTE
-@Vr^Vs'&*]SXkV9q#:H,mdVh+rrGI@rr3ChMuWgT@UaQ)s8Oh?rr3"LSG<*dWW'q<rVlj<rVlt4
-[f7BIrs>hR^Am_@]`3&Pq#:KoXT+iArr3#c0`D"[4Q-8(M.0qOli5^*`Vs<HjS8`Xlb3==WrE#!
-_H[!=!$2";#)nfDs06C@raGm,q#:KNc2U>arr3"cL&V)Qk;N8<!HY:<rrI&?qu6X:JcC<$TDsE~>
-!$2(=!H#(>rrh'#s$tW=rrJF?rr3Mk2uenus8W!s5QB*^s"3^5rr^F#ruM(<!Go">rt2kOs8TTE
-@Vr^Vs'&*]SXkV9q#:H,mdVh+rrGI@rr3ChMuWgT@UaQ)s8Oh?rr3"LSG<*dWW'q<rVlj<rVlt4
-[f7BIrs>hR^Am_@]`3&Pq#:KoXT+iArr3#c0`D"[4Q-8(M.0qOli5^*`Vs<HjS8`Xlb3==WrE#!
-_H[!=!$2";#)nfDs06C@raGm,q#:KNc2U>arr3"cL&V)Qk;N8<!HY:<rrI&?qu6X:JcC<$TDsE~>
-!$2(=!H#(;rrGX?rr3"bLAq2Zju<=uGst.lTg/MU!A3d3rr=)<rrHr?rr3SB@K6@PVn/[Ps8UQZ
-pAb/mEq]M6nLOS<!CGQ?rsY$Js8Q96\riK^s"Wm>rrIY?pAY06<W2pt*W?!?B=@iLr^@-E7DAe$
-aT)9]WV-8lSUg_>!UMN=rsV$Js42%u\n]pugCeK)\cGt,pAY/6WrE#!_H[!=!$2";#"7,Ds03St
-rji)5p&>%`eGfIKQ\GG=!TuB=rr=)9rr=)9rr='js+13Bs*t~>
-!$2(=!H#(;rrGX?rr3"bLAq2Zju<=uGst.lTg/MU!A3d3rr=)<rrHr?rr3SB@K6@PVn/[Ps8UQZ
-pAb/mEq]M6nLOS<!CGQ?rsY$Js8Q96\riK^s"Wm>rrIY?pAY06<W2pt*W?!?B=@iLr^@-E7DAe$
-aT)9]WV-8lSUg_>!UMN=rsV$Js42%u\n]pugCeK)\cGt,pAY/6WrE#!_H[!=!$2";#"7,Ds03St
-rji)5p&>%`eGfIKQ\GG=!TuB=rr=)9rr=)9rr='js+13Bs*t~>
-!$2(=!H#(;rrGX?rr3"bLAq2Zju<=uGst.lTg/MU!A3d3rr=)<rrHr?rr3SB@K6@PVn/[Ps8UQZ
-pAb/mEq]M6nLOS<!CGQ?rsY$Js8Q96\riK^s"Wm>rrIY?pAY06<W2pt*W?!?B=@iLr^@-E7DAe$
-aT)9]WV-8lSUg_>!UMN=rsV$Js42%u\n]pugCeK)\cGt,pAY/6WrE#!_H[!=!$2";#"7,Ds03St
-rji)5p&>%`eGfIKQ\GG=!TuB=rr=)9rr=)9rr='js+13Bs*t~>
-!$2(=!H#(;rrGX?rr3"bLAq2Zju<>?l.=P>h*:l<!A3d3rr=)<rrHr?rr3;:@K1_Qq>^5bJc#HJ
-WcIh5!V%]=rrGI@rr3ChMuQnts8VVDV>i::rr3"LSG)s`a&W*<!$2%<")#(BrVkCOls@F+$N;FT
-&f]0jrrJ[@rr3#c0`D"[4Q,F!jT#8@9^LLmk5PA]/+N?5!HP4>rrKu@rVlj<rVm+KW;6JnZ!6So
-rr=)4rrG[?rr3"cL&V)Qk;N;=!E[;<rrGp?qYpO9JcC<$TDsE~>
-!$2(=!H#(;rrGX?rr3"bLAq2Zju<>?l.=P>h*:l<!A3d3rr=)<rrHr?rr3;:@K1_Qq>^5bJc#HJ
-WcIh5!V%]=rrGI@rr3ChMuQnts8VVDV>i::rr3"LSG)s`a&W*<!$2%<")#(BrVkCOls@F+$N;FT
-&f]0jrrJ[@rr3#c0`D"[4Q,F!jT#8@9^LLmk5PA]/+N?5!HP4>rrKu@rVlj<rVm+KW;6JnZ!6So
-rr=)4rrG[?rr3"cL&V)Qk;N;=!E[;<rrGp?qYpO9JcC<$TDsE~>
-!$2(=!H#(;rrGX?rr3"bLAq2Zju<>?l.=P>h*:l<!A3d3rr=)<rrHr?rr3;:@K1_Qq>^5bJc#HJ
-WcIh5!V%]=rrGI@rr3ChMuQnts8VVDV>i::rr3"LSG)s`a&W*<!$2%<")#(BrVkCOls@F+$N;FT
-&f]0jrrJ[@rr3#c0`D"[4Q,F!jT#8@9^LLmk5PA]/+N?5!HP4>rrKu@rVlj<rVm+KW;6JnZ!6So
-rr=)4rrG[?rr3"cL&V)Qk;N;=!E[;<rrGp?qYpO9JcC<$TDsE~>
-!$2(=!H#(;rrGX?rr31nL&(cKfL5W:!ROO=rrF_?qu6]dn,*+b*W?!MG,kK?r3L5>DR'->r2b#?
-o_\Xf!NL2=rrMNXr;Qff/,fJ`:X9"?q2^a>8(IY>q1kI>5McA>pjf.=rrW,cp&+gja&W*<"t]9D
-s7^9?r;QlmA&J?FoE&p)r;Q]tq<dtTrrJ[@rr3St47iLPoL@j%6hC?Xo02Ho62gfa/+NW=!qu$Y
-r;Qe<WrE#&`aJN?s7%Z>rrVn+_#F?7Z#'C=!$2%<!qYgXr;QdgeGfIPSqQq>s4Kd=rrVdXkPY>]
-o/c@:rr='js+13Bs*t~>
-!$2(=!H#(;rrGX?rr31nL&(cKfL5W:!ROO=rrF_?qu6]dn,*+b*W?!MG,kK?r3L5>DR'->r2b#?
-o_\Xf!NL2=rrMNXr;Qff/,fJ`:X9"?q2^a>8(IY>q1kI>5McA>pjf.=rrW,cp&+gja&W*<"t]9D
-s7^9?r;QlmA&J?FoE&p)r;Q]tq<dtTrrJ[@rr3St47iLPoL@j%6hC?Xo02Ho62gfa/+NW=!qu$Y
-r;Qe<WrE#&`aJN?s7%Z>rrVn+_#F?7Z#'C=!$2%<!qYgXr;QdgeGfIPSqQq>s4Kd=rrVdXkPY>]
-o/c@:rr='js+13Bs*t~>
-!$2(=!H#(;rrGX?rr31nL&(cKfL5W:!ROO=rrF_?qu6]dn,*+b*W?!MG,kK?r3L5>DR'->r2b#?
-o_\Xf!NL2=rrMNXr;Qff/,fJ`:X9"?q2^a>8(IY>q1kI>5McA>pjf.=rrW,cp&+gja&W*<"t]9D
-s7^9?r;QlmA&J?FoE&p)r;Q]tq<dtTrrJ[@rr3St47iLPoL@j%6hC?Xo02Ho62gfa/+NW=!qu$Y
-r;Qe<WrE#&`aJN?s7%Z>rrVn+_#F?7Z#'C=!$2%<!qYgXr;QdgeGfIPSqQq>s4Kd=rrVdXkPY>]
-o/c@:rr='js+13Bs*t~>
-!$2(=!H#(>rseACd5nGXg&M)7QI4)Lrr3GhdF$63s8V?2d3Z]XhYmHT,o6L[%Hc'c(t$ais8R#B
-dC<ffrs3;IdBd]is*:UCd/f_qrr3&r!'pP`%GoLO,LOp&s8Pd:d@H*mrrbg=d?p!orrbd<d?9go
-rrULHCB"5Ef$U6^dF%I`qF/fZJueqOr;P(EIBrbM!HY7=ruS!:PlLd^dF!JXdF%ahf3m"RB?pPW
-d:L_Q@b(M<=T-VJ9(W&^'70_os8Vc>d9V[XdJs6SHdU58nG`FgJ"HW=!P`^Sd/ZZ7rt8-.l2UeO
-dEt%YdFnR"P*XMC7fE>f<64t:!DLl9rr='js+13Bs*t~>
-!$2(=!H#(>rseACd5nGXg&M)7QI4)Lrr3GhdF$63s8V?2d3Z]XhYmHT,o6L[%Hc'c(t$ais8R#B
-dC<ffrs3;IdBd]is*:UCd/f_qrr3&r!'pP`%GoLO,LOp&s8Pd:d@H*mrrbg=d?p!orrbd<d?9go
-rrULHCB"5Ef$U6^dF%I`qF/fZJueqOr;P(EIBrbM!HY7=ruS!:PlLd^dF!JXdF%ahf3m"RB?pPW
-d:L_Q@b(M<=T-VJ9(W&^'70_os8Vc>d9V[XdJs6SHdU58nG`FgJ"HW=!P`^Sd/ZZ7rt8-.l2UeO
-dEt%YdFnR"P*XMC7fE>f<64t:!DLl9rr='js+13Bs*t~>
-!$2(=!H#(>rseACd5nGXg&M)7QI4)Lrr3GhdF$63s8V?2d3Z]XhYmHT,o6L[%Hc'c(t$ais8R#B
-dC<ffrs3;IdBd]is*:UCd/f_qrr3&r!'pP`%GoLO,LOp&s8Pd:d@H*mrrbg=d?p!orrbd<d?9go
-rrULHCB"5Ef$U6^dF%I`qF/fZJueqOr;P(EIBrbM!HY7=ruS!:PlLd^dF!JXdF%ahf3m"RB?pPW
-d:L_Q@b(M<=T-VJ9(W&^'70_os8Vc>d9V[XdJs6SHdU58nG`FgJ"HW=!P`^Sd/ZZ7rt8-.l2UeO
-dEt%YdFnR"P*XMC7fE>f<64t:!DLl9rr='js+13Bs*t~>
-!$2(=#&Sap[f?B>r(@$+rr3(Z92#3^rr\``92GQe!3,lh!.OnH!G*,IrrAVf9)skKrrR(2B)MZ1
-BM31?rr@9B9)sbGrrW'`5lUc`JG`%?W;ceu:eQK?rr`6n98`]J"8GM^OSo+[h)/sHrr?O+9*WB8
-s5lsIUAk/mp&7SaW;?MpSAY=*"i)ONs8Vlk9*XGVs2[i+_#=98_FmPArr2uGrC[.KrVm%q*5DOR
-gAFSD:&b.pX%Q+BrVlnp]);R.Zi*Msrr)j#KFd>Is1J8&!,MT6"-#rHr;HWrLY2M(!J0,*rr^WT
-Zl=SrJcDABJ,~>
-!$2(=#&Sap[f?B>r(@$+rr3(Z92#3^rr\``92GQe!3,lh!.OnH!G*,IrrAVf9)skKrrR(2B)MZ1
-BM31?rr@9B9)sbGrrW'`5lUc`JG`%?W;ceu:eQK?rr`6n98`]J"8GM^OSo+[h)/sHrr?O+9*WB8
-s5lsIUAk/mp&7SaW;?MpSAY=*"i)ONs8Vlk9*XGVs2[i+_#=98_FmPArr2uGrC[.KrVm%q*5DOR
-gAFSD:&b.pX%Q+BrVlnp]);R.Zi*Msrr)j#KFd>Is1J8&!,MT6"-#rHr;HWrLY2M(!J0,*rr^WT
-Zl=SrJcDABJ,~>
-!$2(=#&Sap[f?B>r(@$+rr3(Z92#3^rr\``92GQe!3,lh!.OnH!G*,IrrAVf9)skKrrR(2B)MZ1
-BM31?rr@9B9)sbGrrW'`5lUc`JG`%?W;ceu:eQK?rr`6n98`]J"8GM^OSo+[h)/sHrr?O+9*WB8
-s5lsIUAk/mp&7SaW;?MpSAY=*"i)ONs8Vlk9*XGVs2[i+_#=98_FmPArr2uGrC[.KrVm%q*5DOR
-gAFSD:&b.pX%Q+BrVlnp]);R.Zi*Msrr)j#KFd>Is1J8&!,MT6"-#rHr;HWrLY2M(!J0,*rr^WT
-Zl=SrJcDABJ,~>
-!$2(="/omHD;5'j*S^Spgd'Wo!O?IprrIq?g]%:[^YAbh1[3cr"/0CAFFjICs.B=A~>
-!$2(="/omHD;5'j*S^Spgd'Wo!O?IprrIq?g]%:[^YAbh1[3cr"/0CAFFjICs.B=A~>
-!$2(="/omHD;5'j*S^Spgd'Wo!O?IprrIq?g]%:[^YAbh1[3cr"/0CAFFjICs.B=A~>
-!$0Vi!KE/qrrW+FUtktOk'abprrUPsbhW4"\q/eprrT!Kon!-os+14Fs*t~>
-!$0Vi!KE/qrrW+FUtktOk'abprrUPsbhW4"\q/eprrT!Kon!-os+14Fs*t~>
-!$0Vi!KE/qrrW+FUtktOk'abprrUPsbhW4"\q/eprrT!Kon!-os+14Fs*t~>
-!$0Vi!O2LWrrN)%g]%<B^>&YghTjmU!RKTVrrKn$JcC<$JcGKEJ,~>
-!$0Vi!O2LWrrN)%g]%<B^>&YghTjmU!RKTVrrKn$JcC<$JcGKEJ,~>
-!$0Vi!O2LWrrN)%g]%<B^>&YghTjmU!RKTVrrKn$JcC<$JcGKEJ,~>
-!$.X1!SDh6rrC7A5QK%#rrJ>#p&>&uU\t,l_>Z\"ec#LKV6GONJcC<$hZ&*~>
-!$.X1!SDh6rrC7A5QK%#rrJ>#p&>&uU\t,l_>Z\"ec#LKV6GONJcC<$hZ&*~>
-!$.X1!SDh6rrC7A5QK%#rrJ>#p&>&uU\t,l_>Z\"ec#LKV6GONJcC<$hZ&*~>
-!Zh<Ir$)>4s8S:^o)Ac,,O4Up!^%].ec,^;8E]sO"TCUbZAJS\"Z/[Js,sDOrs&<E>Q=_N_"[j3
-dV8`9[J'V'\lIP@p@\FeS;d+>rrC+<,66HsrrV_<Y5SA'o\A4na8Q#>mVojjs+13$s53j,~>
-!Zh<Ir$)>4s8S:^o)Ac,,O4Up!^%].ec,^;8E]sO"TCUbZAJS\"Z/[Js,sDOrs&<E>Q=_N_"[j3
-dV8`9[J'V'\lIP@p@\FeS;d+>rrC+<,66HsrrV_<Y5SA'o\A4na8Q#>mVojjs+13$s53j,~>
-!Zh<Ir$)>4s8S:^o)Ac,,O4Up!^%].ec,^;8E]sO"TCUbZAJS\"Z/[Js,sDOrs&<E>Q=_N_"[j3
-dV8`9[J'V'\lIP@p@\FeS;d+>rrC+<,66HsrrV_<Y5SA'o\A4na8Q#>mVojjs+13$s53j,~>
-!Zh=>rV6]S3WK-WF0PQ6rrW)nrp9Xf5Ml4O?/GS],PqE@f1,]<&cNmPVK`(?2WiUik^]N0s6V]9
-rrs_D_.`%J]_DF/b>J:\WV6>m\mk:2!r%S@rr3#S7/co^0_,/B!f!3?qu6[sa8Gr=GH(Ijs+13$
-s5<p-~>
-!Zh=>rV6]S3WK-WF0PQ6rrW)nrp9Xf5Ml4O?/GS],PqE@f1,]<&cNmPVK`(?2WiUik^]N0s6V]9
-rrs_D_.`%J]_DF/b>J:\WV6>m\mk:2!r%S@rr3#S7/co^0_,/B!f!3?qu6[sa8Gr=GH(Ijs+13$
-s5<p-~>
-!Zh=>rV6]S3WK-WF0PQ6rrW)nrp9Xf5Ml4O?/GS],PqE@f1,]<&cNmPVK`(?2WiUik^]N0s6V]9
-rrs_D_.`%J]_DF/b>J:\WV6>m\mk:2!r%S@rr3#S7/co^0_,/B!f!3?qu6[sa8Gr=GH(Ijs+13$
-s5<p-~>
-!$2";!S0d=rrR#CrV$6nilfOArVllVrlY;kr;QfHd/<nK3o^1dHN4$"rlYl+s8V$Is3AgBs8Us!
-bPB?;rr2uLrlYT(s8Ufr(X("[rVlj<qu7B09`MVcs8Q9ls2[$bs8UT^-HjTqrr2uBrlY`7s8Pal
-s0OVbs8UL?rlY<.rr3,OFoRN7pAY0)@f?<-qpkZF"k`YNs/C)<rrM+mrr3&R:%\Da!F<J;rrH-?
-qu6[kd"24Js+14.s*t~>
-!$2";!S0d=rrR#CrV$6nilfOArVllVrlY;kr;QfHd/<nK3o^1dHN4$"rlYl+s8V$Is3AgBs8Us!
-bPB?;rr2uLrlYT(s8Ufr(X("[rVlj<qu7B09`MVcs8Q9ls2[$bs8UT^-HjTqrr2uBrlY`7s8Pal
-s0OVbs8UL?rlY<.rr3,OFoRN7pAY0)@f?<-qpkZF"k`YNs/C)<rrM+mrr3&R:%\Da!F<J;rrH-?
-qu6[kd"24Js+14.s*t~>
-!$2";!S0d=rrR#CrV$6nilfOArVllVrlY;kr;QfHd/<nK3o^1dHN4$"rlYl+s8V$Is3AgBs8Us!
-bPB?;rr2uLrlYT(s8Ufr(X("[rVlj<qu7B09`MVcs8Q9ls2[$bs8UT^-HjTqrr2uBrlY`7s8Pal
-s0OVbs8UL?rlY<.rr3,OFoRN7pAY0)@f?<-qpkZF"k`YNs/C)<rrM+mrr3&R:%\Da!F<J;rrH-?
-qu6[kd"24Js+14.s*t~>
-!$2%<!luR\qu6\6YP.tuSPTp\rr3#PGQ(D>@)`*E!@8NZrrG1?rVloGD>m?GC!H[BQ*41aD:&;e
-4]%qNE7=jeFoG2CF4L;C:^KrpQMpg`*UNe4CeG:8:p'ct\P`?&!J]_2rrF"/r_NWSlgOiS\mkX<
-!UMN=rrkOCs8T'>q>UNBCZ53k!F<J;rrH-?qu6[kd"24Js+14.s*t~>
-!$2%<!luR\qu6\6YP.tuSPTp\rr3#PGQ(D>@)`*E!@8NZrrG1?rVloGD>m?GC!H[BQ*41aD:&;e
-4]%qNE7=jeFoG2CF4L;C:^KrpQMpg`*UNe4CeG:8:p'ct\P`?&!J]_2rrF"/r_NWSlgOiS\mkX<
-!UMN=rrkOCs8T'>q>UNBCZ53k!F<J;rrH-?qu6[kd"24Js+14.s*t~>
-!$2%<!luR\qu6\6YP.tuSPTp\rr3#PGQ(D>@)`*E!@8NZrrG1?rVloGD>m?GC!H[BQ*41aD:&;e
-4]%qNE7=jeFoG2CF4L;C:^KrpQMpg`*UNe4CeG:8:p'ct\P`?&!J]_2rrF"/r_NWSlgOiS\mkX<
-!UMN=rrkOCs8T'>q>UNBCZ53k!F<J;rrH-?qu6[kd"24Js+14.s*t~>
-!$2%<".O.FUAOrj*VB@42Wk#=!JQm>rrLY@rVlnMHN*pI`0)9pTDnikCp<p=&\DKOs$g8gs0HG>
->J^=[s/L,:rrJj?rr2s=qYpO9li."Q0`:qO+T;<>!Nj`DrrEjhrr3"*^@2(&\mkX<$hSPIs8TTP
-mJm3cF8Gn<b'_b:rrHE?qu6[sa8>l;:!eIkJcC<$i;\<~>
-!$2%<".O.FUAOrj*VB@42Wk#=!JQm>rrLY@rVlnMHN*pI`0)9pTDnikCp<p=&\DKOs$g8gs0HG>
->J^=[s/L,:rrJj?rr2s=qYpO9li."Q0`:qO+T;<>!Nj`DrrEjhrr3"*^@2(&\mkX<$hSPIs8TTP
-mJm3cF8Gn<b'_b:rrHE?qu6[sa8>l;:!eIkJcC<$i;\<~>
-!$2%<".O.FUAOrj*VB@42Wk#=!JQm>rrLY@rVlnMHN*pI`0)9pTDnikCp<p=&\DKOs$g8gs0HG>
->J^=[s/L,:rrJj?rr2s=qYpO9li."Q0`:qO+T;<>!Nj`DrrEjhrr3"*^@2(&\mkX<$hSPIs8TTP
-mJm3cF8Gn<b'_b:rrHE?qu6[sa8>l;:!eIkJcC<$i;\<~>
-!$1t:!V[r=rrJ%?o`"qMk5PA]KpVf=!S'a9rrg)o++'CSrrHr?rr3\E@K6?sf)Pd*])Q!NruM->
-ErZ0&rcJ66HN*pE*W#d9*UE_+m4eJ<!1Ee.!5nR2!$2%<!FEM/rrK]?r;QrH:B1>t_uBZ:WH7t:
-!mH/@qYpS%^\e$3<QG":!DUpls+13$s5<p-~>
-!$1t:!V[r=rrJ%?o`"qMk5PA]KpVf=!S'a9rrg)o++'CSrrHr?rr3\E@K6?sf)Pd*])Q!NruM->
-ErZ0&rcJ66HN*pE*W#d9*UE_+m4eJ<!1Ee.!5nR2!$2%<!FEM/rrK]?r;QrH:B1>t_uBZ:WH7t:
-!mH/@qYpS%^\e$3<QG":!DUpls+13$s5<p-~>
-!$1t:!V[r=rrJ%?o`"qMk5PA]KpVf=!S'a9rrg)o++'CSrrHr?rr3\E@K6?sf)Pd*])Q!NruM->
-ErZ0&rcJ66HN*pE*W#d9*UE_+m4eJ<!1Ee.!5nR2!$2%<!FEM/rrK]?r;QrH:B1>t_uBZ:WH7t:
-!mH/@qYpS%^\e$3<QG":!DUpls+13$s5<p-~>
-!$1t:!V[r>rrRqDqt0mh2Wk#=!JQm>[email protected]/lXCp<p="hS4Cs$kT;rs;oGruM->ErV/d
-rhfd3HN*pE*W#d9*UE_+m4eG;!3#mp!IDl_rr=)<rrHH?n,EF"@f660mZ3s:MsC<A!NC/<rrU\m
-deWnD?,-::!EI2;rrGj@JcC<$JcF[.J,~>
-!$1t:!V[r>rrRqDqt0mh2Wk#=!JQm>[email protected]/lXCp<p="hS4Cs$kT;rs;oGruM->ErV/d
-rhfd3HN*pE*W#d9*UE_+m4eG;!3#mp!IDl_rr=)<rrHH?n,EF"@f660mZ3s:MsC<A!NC/<rrU\m
-deWnD?,-::!EI2;rrGj@JcC<$JcF[.J,~>
-!$1t:!V[r>rrRqDqt0mh2Wk#=!JQm>[email protected]/lXCp<p="hS4Cs$kT;rs;oGruM->ErV/d
-rhfd3HN*pE*W#d9*UE_+m4eG;!3#mp!IDl_rr=)<rrHH?n,EF"@f660mZ3s:MsC<A!NC/<rrU\m
-deWnD?,-::!EI2;rrGj@JcC<$JcF[.J,~>
-"!.ESQ2^dapEon>!f3H@oD\hLk5PA]KpVf=!S'a>rrH1pr;QdYir/lXCp<p="hS4Cs$kT;rsi8L
-ruM->ErT(\s8U@jHN*pI*WQ/ET`4rl\mt+,#jj>Gs-L=s;uQ^q!H5+8rr=)<rrHH?pAY3*40AJ]
-!P2b;rr]NAGGY9<!pbT@rr3&[?J>5T!h#5@qu6[sa8Gr=N19J;rrRp:iIV#[s+146s*t~>
-"!.ESQ2^dapEon>!f3H@oD\hLk5PA]KpVf=!S'a>rrH1pr;QdYir/lXCp<p="hS4Cs$kT;rsi8L
-ruM->ErT(\s8U@jHN*pI*WQ/ET`4rl\mt+,#jj>Gs-L=s;uQ^q!H5+8rr=)<rrHH?pAY3*40AJ]
-!P2b;rr]NAGGY9<!pbT@rr3&[?J>5T!h#5@qu6[sa8Gr=N19J;rrRp:iIV#[s+146s*t~>
-"!.ESQ2^dapEon>!f3H@oD\hLk5PA]KpVf=!S'a>rrH1pr;QdYir/lXCp<p="hS4Cs$kT;rsi8L
-ruM->ErT(\s8U@jHN*pI*WQ/ET`4rl\mt+,#jj>Gs-L=s;uQ^q!H5+8rr=)<rrHH?pAY3*40AJ]
-!P2b;rr]NAGGY9<!pbT@rr3&[?J>5T!h#5@qu6[sa8Gr=N19J;rrRp:iIV#[s+146s*t~>
-"!.F7L]/>!-0>1,OHfM3rs4/s"rf])s7("+*W\IhrVlmE(B"153o^,<!Ua.j*X,I.s8PR>r;R72
-_>iTrWcJ.*7ii^IO*^g*"P=b:D".H(!U2E,rs8S9*Zg(.s5bC&*W_5mq#:=7rVln)^@qR.V#ZbY
-rrK]?qu6clO,!<)rrJ(@rr3#R#lG_DoD\ajH_UB:!EI2<rrHl?qu6_+!8)l&JcC<$kl6/~>
-"!.F7L]/>!-0>1,OHfM3rs4/s"rf])s7("+*W\IhrVlmE(B"153o^,<!Ua.j*X,I.s8PR>r;R72
-_>iTrWcJ.*7ii^IO*^g*"P=b:D".H(!U2E,rs8S9*Zg(.s5bC&*W_5mq#:=7rVln)^@qR.V#ZbY
-rrK]?qu6clO,!<)rrJ(@rr3#R#lG_DoD\ajH_UB:!EI2<rrHl?qu6_+!8)l&JcC<$kl6/~>
-"!.F7L]/>!-0>1,OHfM3rs4/s"rf])s7("+*W\IhrVlmE(B"153o^,<!Ua.j*X,I.s8PR>r;R72
-_>iTrWcJ.*7ii^IO*^g*"P=b:D".H(!U2E,rs8S9*Zg(.s5bC&*W_5mq#:=7rVln)^@qR.V#ZbY
-rrK]?qu6clO,!<)rrJ(@rr3#R#lG_DoD\ajH_UB:!EI2<rrHl?qu6_+!8)l&JcC<$kl6/~>
-!Zh=@r;Q]q!<2Qhr;Q]qr;QWos8Mrr!<2lqr;Q]q!<2lq!<2or!ri6"rVcitrr)lrrqucsct2PC
-rr2osr;QHj!<2rs!<2Wj!Jcp<rrg.X*?E#qs8W)qrrW1K\,QF)rr2ouUltZU"L]<k*6nH^!L9>S
-s8W(Ls+13$s6'E4~>
-!Zh=@r;Q]q!<2Qhr;Q]qr;QWos8Mrr!<2lqr;Q]q!<2lq!<2or!ri6"rVcitrr)lrrqucsct2PC
-rr2osr;QHj!<2rs!<2Wj!Jcp<rrg.X*?E#qs8W)qrrW1K\,QF)rr2ouUltZU"L]<k*6nH^!L9>S
-s8W(Ls+13$s6'E4~>
-!Zh=@r;Q]q!<2Qhr;Q]qr;QWos8Mrr!<2lqr;Q]q!<2lq!<2or!ri6"rVcitrr)lrrqucsct2PC
-rr2osr;QHj!<2rs!<2Wj!Jcp<rrg.X*?E#qs8W)qrrW1K\,QF)rr2ouUltZU"L]<k*6nH^!L9>S
-s8W(Ls+13$s6'E4~>
-!$-XjhZ!ZCKWKb)JcC<$W;hA~>
-!$-XjhZ!ZCKWKb)JcC<$W;hA~>
-!$-XjhZ!ZCKWKb)JcC<$W;hA~>
-!$-XjhZ!VoV1JYts+13Js*t~>
-!$-XjhZ!VoV1JYts+13Js*t~>
-!$-XjhZ!VoV1JYts+13Js*t~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-"!.EGKDtlRpH/DRMZ3VYn3d5LP5bIij\#Q@RfEEb3<0$WGlA]a6N$i_#?;`a8,rVfC&T+R;>l(G
-JcC<$JcE=]J,~>
-"!.EGKDtlRpH/DRMZ3VYn3d5LP5bIij\#Q@RfEEb3<0$WGlA]a6N$i_#?;`a8,rVfC&T+R;>l(G
-JcC<$JcE=]J,~>
-"!.EGKDtlRpH/DRMZ3VYn3d5LP5bIij\#Q@RfEEb3<0$WGlA]a6N$i_#?;`a8,rVfC&T+R;>l(G
-JcC<$JcE=]J,~>
-"!.E>FoMCDpEop4IfB?]mOnO*LB%;6+?0=\NrT.U,6.[sQi@!ceO]]>#=@//1]RJsW;cet`*%Zk
-JcC<$JcE=]J,~>
-"!.E>FoMCDpEop4IfB?]mOnO*LB%;6+?0=\NrT.U,6.[sQi@!ceO]]>#=@//1]RJsW;cet`*%Zk
-JcC<$JcE=]J,~>
-"!.E>FoMCDpEop4IfB?]mOnO*LB%;6+?0=\NrT.U,6.[sQi@!ceO]]>#=@//1]RJsW;cet`*%Zk
-JcC<$JcE=]J,~>
-"!.E>FoMCDpEop4?iIkU[4_KFLB#Xsj#@!uNrT.U,6.[sQi@!ceO]]>#=@//1]RJsJ,[7bPZ`S;
-JcC<$JcE=]J,~>
-"!.E>FoMCDpEop4?iIkU[4_KFLB#Xsj#@!uNrT.U,6.[sQi@!ceO]]>#=@//1]RJsJ,[7bPZ`S;
-JcC<$JcE=]J,~>
-"!.E>FoMCDpEop4?iIkU[4_KFLB#Xsj#@!uNrT.U,6.[sQi@!ceO]]>#=@//1]RJsJ,[7bPZ`S;
-JcC<$JcE=]J,~>
-"!.E>FoMCDpEop4/cJof<%e3:L;e#pju<=#NrT.U,6.[sQi@!neO]`?`bsu(1]RJs4T/F`P_&jc
-s+13$s185\~>
-"!.E>FoMCDpEop4/cJof<%e3:L;e#pju<=#NrT.U,6.[sQi@!neO]`?`bsu(1]RJs4T/F`P_&jc
-s+13$s185\~>
-"!.E>FoMCDpEop4/cJof<%e3:L;e#pju<=#NrT.U,6.[sQi@!neO]`?`bsu(1]RJs4T/F`P_&jc
-s+13$s185\~>
-"!.E>FoMCDN@+[tIfB?]mOnO*7t'7oju<=#NrT.U,6.[sQi@!neO]`?@(lU)1]RJsW.Fu"s+13$
-s0_lW~>
-"!.E>FoMCDN@+[tIfB?]mOnO*7t'7oju<=#NrT.U,6.[sQi@!neO]`?@(lU)1]RJsW.Fu"s+13$
-s0_lW~>
-"!.E>FoMCDN@+[tIfB?]mOnO*7t'7oju<=#NrT.U,6.[sQi@!neO]`?@(lU)1]RJsW.Fu"s+13$
-s0_lW~>
-"!.EqJc9EfN$eRsIfB?]mOnO*:>,[Iju<=#4DS_H%ZgY6I/[miEjG_O-r4Vf'q,*@H2_RZNIh+\
-s+13$s1//[~>
-"!.EqJc9EfN$eRsIfB?]mOnO*:>,[Iju<=#4DS_H%ZgY6I/[miEjG_O-r4Vf'q,*@H2_RZNIh+\
-s+13$s1//[~>
-"!.EqJc9EfN$eRsIfB?]mOnO*:>,[Iju<=#4DS_H%ZgY6I/[miEjG_O-r4Vf'q,*@H2_RZNIh+\
-s+13$s1//[~>
-"!.FAg]"G\n0\1pfDbdQqS3'fgA_*SpVQscrNQKo5QCc2rilU?s8RLcrilTd;#gR>rilI@JcC<$
-JcC<$\c70~>
-"!.FAg]"G\n0\1pfDbdQqS3'fgA_*SpVQscrNQKo5QCc2rilU?s8RLcrilTd;#gR>rilI@JcC<$
-JcC<$\c70~>
-"!.FAg]"G\n0\1pfDbdQqS3'fgA_*SpVQscrNQKo5QCc2rilU?s8RLcrilTd;#gR>rilI@JcC<$
-JcC<$\c70~>
-"!.EOOT,7\pEo5+!Sp!8rrM9Lrr3#lh1>TWs+13$s0DZT~>
-"!.EOOT,7\pEo5+!Sp!8rrM9Lrr3#lh1>TWs+13$s0DZT~>
-"!.EOOT,7\pEo5+!Sp!8rrM9Lrr3#lh1>TWs+13$s0DZT~>
-"!.F:N;agu,jt!u!W;G<s+13$s+13Es*t~>
-"!.F:N;agu,jt!u!W;G<s+13$s+13Es*t~>
-"!.F:N;agu,jt!u!W;G<s+13$s+13Es*t~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$1k7!Tr3hs+13$s+130s*t~>
-!$1k7!Tr3hs+13$s+130s*t~>
-!$1k7!Tr3hs+13$s+130s*t~>
-!$1k7!M=gls+13$s+130s*t~>
-!$1k7!M=gls+13$s+130s*t~>
-!$1k7!M=gls+13$s+130s*t~>
-!$1k7!M=gls+13$s+130s*t~>
-!$1k7!M=gls+13$s+130s*t~>
-!$1k7!M=gls+13$s+130s*t~>
-"!.FA\c-1DC]FF,IfB?Jon%bpJcC<$JcCo5J,~>
-"!.FA\c-1DC]FF,IfB?Jon%bpJcC<$JcCo5J,~>
-"!.FA\c-1DC]FF,IfB?Jon%bpJcC<$JcCo5J,~>
-"!.EWHiCG[ZXj*.IfKF\:r@kaJcC<$JcCo5J,~>
-"!.EWHiCG[ZXj*.IfKF\:r@kaJcC<$JcCo5J,~>
-"!.EWHiCG[ZXj*.IfKF\:r@kaJcC<$JcCo5J,~>
-"!.E>FoMCHpEop4IX`oYeq*jPs+13$s,m>3~>
-"!.E>FoMCHpEop4IX`oYeq*jPs+13$s,m>3~>
-"!.E>FoMCHpEop4IX`oYeq*jPs+13$s,m>3~>
-"!.E>FoMCGpEop4%[H&MJcC<$JcC<$OT0h~>
-"!.E>FoMCGpEop4%[H&MJcC<$JcC<$OT0h~>
-"!.E>FoMCGpEop4%[H&MJcC<$JcC<$OT0h~>
-"!.E>FoMCHpEop4IXWfXf7EsQs+13$s,m>3~>
-"!.E>FoMCHpEop4IXWfXf7EsQs+13$s,m>3~>
-"!.E>FoMCHpEop4IXWfXf7EsQs+13$s,m>3~>
-"!.EWHiCJ\Zt'-.IfKF[:W.haJcC<$JcCo5J,~>
-"!.EWHiCJ\Zt'-.IfKF[:W.haJcC<$JcCo5J,~>
-"!.EWHiCJ\Zt'-.IfKF[:W.haJcC<$JcCo5J,~>
-"!.FA\Gg"ACB+=QZ2Xb(omhVnJcC<$JcCo5J,~>
-"!.FA\Gg"ACB+=QZ2Xb(omhVnJcC<$JcCo5J,~>
-"!.FA\Gg"ACB+=QZ2Xb(omhVnJcC<$JcCo5J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$1>(!5\M"!/Q4+JcC<$JcDMFJ,~>
-!$1>(!5\M"!/Q4+JcC<$JcDMFJ,~>
-!$1>(!5\M"!/Q4+JcC<$JcDMFJ,~>
-!$1>(!NTW+fE%aPJcC<$JcC<$U]5i~>
-!$1>(!NTW+fE%aPJcC<$JcC<$U]5i~>
-!$1>(!NTW+fE%aPJcC<$JcC<$U]5i~>
-!$2";!UqE7rrS:OqY'piX)\(;!Phrks+13$s+13Fs*t~>
-!$2";!UqE7rrS:OqY'piX)\(;!Phrks+13$s+13Fs*t~>
-!$2";!UqE7rrS:OqY'piX)\(;!Phrks+13$s+13Fs*t~>
-!$2%<!o?]]rVlqMU\FN_!NU5<rrKo?JcC<$JcC<$U]5i~>
-!$2%<!o?]]rVlqMU\FN_!NU5<rrKo?JcC<$JcC<$U]5i~>
-!$2%<!o?]]rVlqMU\FN_!NU5<rrKo?JcC<$JcC<$U]5i~>
-!$2(="4M)A*W5p=I\Q`7rrK0?r;Qf5>_2p+s+13$s.fUE~>
-!$2(="4M)A*W5p=I\Q`7rrK0?r;Qf5>_2p+s+13$s.fUE~>
-!$2(="4M)A*W5p=I\Q`7rrK0?r;Qf5>_2p+s+13$s.fUE~>
-#9EjEc[=+>*W,j;JsuK7!NU5<rrKo?JcC<$JcC<$U]5i~>
-#9EjEc[=+>*W,j;JsuK7!NU5<rrKo?JcC<$JcC<$U]5i~>
-#9EjEc[=+>*W,j;JsuK7!NU5<rrKo?JcC<$JcC<$U]5i~>
-#9EilJ'@rm*W#d9*VfX8X)\(;!Phrks+13$s+13Fs*t~>
-#9EilJ'@rm*W#d9*VfX8X)\(;!Phrks+13$s+13Fs*t~>
-#9EilJ'@rm*W#d9*VfX8X)\(;!Phrks+13$s+13Fs*t~>
-"!.E>.fNZR$Zu=H!Ht@8rrK0?r;Qf5>_2p+s+13$s.fUE~>
-"!.E>.fNZR$Zu=H!Ht@8rrK0?r;Qf5>_2p+s+13$s.fUE~>
-"!.E>.fNZR$Zu=H!Ht@8rrK0?r;Qf5>_2p+s+13$s.fUE~>
-!Zh=*rP/FLao25@FK>?7rrK0?r;Qf5>_2p+s+13$s.fUE~>
-!Zh=*rP/FLao25@FK>?7rrK0?r;Qf5>_2p+s+13$s.fUE~>
-!Zh=*rP/FLao25@FK>?7rrK0?r;Qf5>_2p+s+13$s.fUE~>
-!$1t:!$2%<!dUd@p\t8pEW#h;^g)HjJcC<$JcDMFJ,~>
-!$1t:!$2%<!dUd@p\t8pEW#h;^g)HjJcC<$JcDMFJ,~>
-!$1t:!$2%<!dUd@p\t8pEW#h;^g)HjJcC<$JcDMFJ,~>
-!$1t:!&FQR!g'2VpAY/oEW#h;^g)HjJcC<$JcDMFJ,~>
-!$1t:!&FQR!g'2VpAY/oEW#h;^g)HjJcC<$JcDMFJ,~>
-!$1t:!&FQR!g'2VpAY/oEW#h;^g)HjJcC<$JcDMFJ,~>
-!$1>(!NU5<rrKo?JcC<$JcC<$U]5i~>
-!$1>(!NU5<rrKo?JcC<$JcC<$U]5i~>
-!$1>(!NU5<rrKo?JcC<$JcC<$U]5i~>
-!$1>(!NSrmXT=#YJcC<$JcC<$U]5i~>
-!$1>(!NSrmXT=#YJcC<$JcC<$U]5i~>
-!$1>(!NSrmXT=#YJcC<$JcC<$U]5i~>
-!$1>(!71L[!2G,FJcC<$JcDMFJ,~>
-!$1>(!71L[!2G,FJcC<$JcDMFJ,~>
-!$1>(!71L[!2G,FJcC<$JcDMFJ,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-!$-XjJcC<$JcC?%J,~>
-%%EndData
-showpage
-%%Trailer
-end
-%%EOF
diff --git a/lib/stdlib/doc/src/ushell2.gif b/lib/stdlib/doc/src/ushell2.gif
deleted file mode 100644
index 273cf2078a..0000000000
--- a/lib/stdlib/doc/src/ushell2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/stdlib/doc/src/ushell2.ps b/lib/stdlib/doc/src/ushell2.ps
deleted file mode 100644
index e6db3c2be2..0000000000
--- a/lib/stdlib/doc/src/ushell2.ps
+++ /dev/null
@@ -1,404 +0,0 @@
-%!PS-Adobe-3.0
-%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner
-%%Title: ushell2.ps
-%%CreationDate: Mon Mar 16 09:52:14 2009
-%%DocumentData: Clean7Bit
-%%LanguageLevel: 2
-%%Pages: 1
-%%BoundingBox: 14 14 468 74
-%%EndComments
-%%BeginProlog
-% Use own dictionary to avoid conflicts
-10 dict begin
-%%EndProlog
-%%Page: 1 1
-% Translate for offset
-14.173228346456694 14.173228346456694 translate
-% Translate to begin of first scanline
-0 59.527559055118118 translate
-453.54330708661422 -59.527559055118118 scale
-% Image geometry
-640 84 8
-% Transformation matrix
-[ 640 0 0 84 0 0 ]
-% Strings to hold RGB-samples per scanline
-/rstr 640 string def
-/gstr 640 string def
-/bstr 640 string def
-{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
-{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
-{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
-true 3
-%%BeginData: 18704 ASCII Bytes
-colorimage
-J`MCCJ`MCCJ`M=~>
-J`MCCJ`MCCJ`M=~>
-J`MCCJ`MCCJ`M=~>
-!)nG7JO+iQJO+lRJ,~>
-!)nG7JO+iQJO+lRJ,~>
-!)nG7JO+iQJO+lRJ,~>
-!D=/Y=b0_,=b0_.=b$~>
-!D=/Y=b0_,=b0_.=b$~>
-!D=/Y=b0_,=b0_.=b$~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M>rrKOJQ2^i3JcC<$JcFU,J,~>
-!D>M>rrKOJQ2^i3JcC<$JcFU,J,~>
-!D>M>rrKOJQ2^i3JcC<$JcFU,J,~>
-"%t`UXo(ooJ,'$ES](+!!dROKr;Qh<:2'>#!I!f.rr]@2s).a0!581-!+,Ru!6ss3!kNp@p\t9X
-H-uWnOA=s3rrK.0nG`Jtr;QbGr_<HIrVlo/@tFZ2s+14-s*t~>
-"%t`UXo(ooJ,'$ES](+!!dROKr;Qh<:2'>#!I!f.rr]@2s).a0!581-!+,Ru!6ss3!kNp@p\t9X
-H-uWnOA=s3rrK.0nG`Jtr;QbGr_<HIrVlo/@tFZ2s+14-s*t~>
-"%t`UXo(ooJ,'$ES](+!!dROKr;Qh<:2'>#!I!f.rr]@2s).a0!581-!+,Ru!6ss3!kNp@p\t9X
-H-uWnOA=s3rrK.0nG`Jtr;QbGr_<HIrVlo/@tFZ2s+14-s*t~>
-"A:iVM0T!F!8RAL!HP42rrUp#*W5p=fZ5E4rrG1@rr3+VQ2`JQrQbK2q#:?CrQbLB\*j7sS:L>5
-!T-**rrJOjli.%FchRG<!HlihrrIe?nc&Yn]MJP,!J%!FcN0Vnrr3#u++aHCs+14-s*t~>
-"A:iVM0T!F!8RAL!HP42rrUp#*W5p=fZ5E4rrG1@rr3+VQ2`JQrQbK2q#:?CrQbLB\*j7sS:L>5
-!T-**rrJOjli.%FchRG<!HlihrrIe?nc&Yn]MJP,!J%!FcN0Vnrr3#u++aHCs+14-s*t~>
-"A:iVM0T!F!8RAL!HP42rrUp#*W5p=fZ5E4rrG1@rr3+VQ2`JQrQbK2q#:?CrQbLB\*j7sS:L>5
-!T-**rrJOjli.%FchRG<!HlihrrIe?nc&Yn]MJP,!J%!FcN0Vnrr3#u++aHCs+14-s*t~>
-"A:iVM3Rl:!;QQc#kn;uEiSm+o_8@b!;HKb!;HEk!$;%;!V[r6rs;$Hs8VtORf>#.rq$3eoD\lN
-QMU(M!l&CArVllrrU^6ks5-$;rq$<ks8W#qoFLs$rV6Ego^r._r:GB$o^qnX!W2]krs&2ss8)B[
-rVlg+qXdY#o_/=bKUDN+o_/%Z$2J#IrQSC<s'rY>rrMrfrVloH97d+os+14.s*t~>
-"A:iVM3Rl:!;QQc#kn;uEiSm+o_8@b!;HKb!;HEk!$;%;!V[r6rs;$Hs8VtORf>#.rq$3eoD\lN
-QMU(M!l&CArVllrrU^6ks5-$;rq$<ks8W#qoFLs$rV6Ego^r._r:GB$o^qnX!W2]krs&2ss8)B[
-rVlg+qXdY#o_/=bKUDN+o_/%Z$2J#IrQSC<s'rY>rrMrfrVloH97d+os+14.s*t~>
-"A:iVM3Rl:!;QQc#kn;uEiSm+o_8@b!;HKb!;HEk!$;%;!V[r6rs;$Hs8VtORf>#.rq$3eoD\lN
-QMU(M!l&CArVllrrU^6ks5-$;rq$<ks8W#qoFLs$rV6Ego^r._r:GB$o^qnX!W2]krs&2ss8)B[
-rVlg+qXdY#o_/=bKUDN+o_/%Z$2J#IrQSC<s'rY>rrMrfrVloH97d+os+14.s*t~>
-#>7/YM1+"-g&D!PlY?DI$r#a^Efa$E-rf=.k?@j5!F+acrr=,;rrMj@o`#1<s8Sp?s8O^er[7f!
-nFce_n:I\.rrK]@r;QcHr?qfQqqj5tr[7lYrV35f-kO2nd:1^L-n*1:a!_W=-n+farrK!?rr35q
-.KBF2-jn]-rsk_N%3R&fs8Rb&=stdhj7rWTKtI?a"NGcfA%MI8!T6+ls+13$s5<p-~>
-#>7/YM1+"-g&D!PlY?DI$r#a^Efa$E-rf=.k?@j5!F+acrr=,;rrMj@o`#1<s8Sp?s8O^er[7f!
-nFce_n:I\.rrK]@r;QcHr?qfQqqj5tr[7lYrV35f-kO2nd:1^L-n*1:a!_W=-n+farrK!?rr35q
-.KBF2-jn]-rsk_N%3R&fs8Rb&=stdhj7rWTKtI?a"NGcfA%MI8!T6+ls+13$s5<p-~>
-#>7/YM1+"-g&D!PlY?DI$r#a^Efa$E-rf=.k?@j5!F+acrr=,;rrMj@o`#1<s8Sp?s8O^er[7f!
-nFce_n:I\.rrK]@r;QcHr?qfQqqj5tr[7lYrV35f-kO2nd:1^L-n*1:a!_W=-n+farrK!?rr35q
-.KBF2-jn]-rsk_N%3R&fs8Rb&=stdhj7rWTKtI?a"NGcfA%MI8!T6+ls+13$s5<p-~>
-#>7/YM'th_:B(7oI@pN=%,$43E\H&Es1hq?B=@g>!OQP=rr=,;rrMj@o`#1<s8Sp?s8Qb.rr3"H
-U%SEdTmZ8-!P2e8rrb=Bh[t\DrrXkBdn0N<#U90GWZSDDruV1>!J6g6rs#?Ds3C3-.K08I6JDA;
-!EI5>rs"-+b5_Li9CVrcA%M^:\[g>jrrM%@JcC<$JcF[.J,~>
-#>7/YM'th_:B(7oI@pN=%,$43E\H&Es1hq?B=@g>!OQP=rr=,;rrMj@o`#1<s8Sp?s8Qb.rr3"H
-U%SEdTmZ8-!P2e8rrb=Bh[t\DrrXkBdn0N<#U90GWZSDDruV1>!J6g6rs#?Ds3C3-.K08I6JDA;
-!EI5>rs"-+b5_Li9CVrcA%M^:\[g>jrrM%@JcC<$JcF[.J,~>
-#>7/YM'th_:B(7oI@pN=%,$43E\H&Es1hq?B=@g>!OQP=rr=,;rrMj@o`#1<s8Sp?s8Qb.rr3"H
-U%SEdTmZ8-!P2e8rrb=Bh[t\DrrXkBdn0N<#U90GWZSDDruV1>!J6g6rs#?Ds3C3-.K08I6JDA;
-!EI5>rs"-+b5_Li9CVrcA%M^:\[g>jrrM%@JcC<$JcF[.J,~>
-"A:iVM3Ro;!O.@YS-6(rs)P.=rrg,Cs(?9LS,mM@rVlj=qu6]k-M7<@Ff=JZXSVqtI%g96!p59A
-mJd3uA,Q?,li!=U,37WFrVlsOnC'u-rraPCs/L,=rr@3@rrI_@p&>5nG5k:_oI9b=!CGN<rrH-@
-rVlnOR/[*ddS'*0#%P7Eo4(4*rVloV4b<Was+14.s*t~>
-"A:iVM3Ro;!O.@YS-6(rs)P.=rrg,Cs(?9LS,mM@rVlj=qu6]k-M7<@Ff=JZXSVqtI%g96!p59A
-mJd3uA,Q?,li!=U,37WFrVlsOnC'u-rraPCs/L,=rr@3@rrI_@p&>5nG5k:_oI9b=!CGN<rrH-@
-rVlnOR/[*ddS'*0#%P7Eo4(4*rVloV4b<Was+14.s*t~>
-"A:iVM3Ro;!O.@YS-6(rs)P.=rrg,Cs(?9LS,mM@rVlj=qu6]k-M7<@Ff=JZXSVqtI%g96!p59A
-mJd3uA,Q?,li!=U,37WFrVlsOnC'u-rraPCs/L,=rr@3@rrI_@p&>5nG5k:_oI9b=!CGN<rrH-@
-rVlnOR/[*ddS'*0#%P7Eo4(4*rVloV4b<Was+14.s*t~>
-"A:iVM3Rl:!3lHR"G!EMEiT-="Me=CB3bCd!4;_)!$;%;!V[r5rr`6B_HQd8!IUU7rrKi?m/I*t
-A,ZE.oRHgj"!$CZ55kK`/b%4\rVm!Equ<[:qYpSJS+ZdcVKVu6ch&[brrGI?r;QdtaSl,>KUDc=
-!RaX1rrHW@rr3#'D#OA7i&uYkJcC<$i;\<~>
-"A:iVM3Rl:!3lHR"G!EMEiT-="Me=CB3bCd!4;_)!$;%;!V[r5rr`6B_HQd8!IUU7rrKi?m/I*t
-A,ZE.oRHgj"!$CZ55kK`/b%4\rVm!Equ<[:qYpSJS+ZdcVKVu6ch&[brrGI?r;QdtaSl,>KUDc=
-!RaX1rrHW@rr3#'D#OA7i&uYkJcC<$i;\<~>
-"A:iVM3Rl:!3lHR"G!EMEiT-="Me=CB3bCd!4;_)!$;%;!V[r5rr`6B_HQd8!IUU7rrKi?m/I*t
-A,ZE.oRHgj"!$CZ55kK`/b%4\rVm!Equ<[:qYpSJS+ZdcVKVu6ch&[brrGI?r;QdtaSl,>KUDc=
-!RaX1rrHW@rr3#'D#OA7i&uYkJcC<$i;\<~>
-"A:iVM3Ro;!O'H@rrgMCs)P.=rrg,Cs(Ae8rr=,;rrMj@o`#$m+2V4\rrITArr3"HU&P&nhI3>\
-rrVG(_X.:(jbC#[email protected]($+6gRf<<h/b%4\rVm!Equ<[:qYp\MS,`M0q#:PqG,("4kUHK1
-!CGN<rs)QFs6>F?KUDc=!RaX1rrHW@rr3#'D#XG9rb/]js+13$s5<p-~>
-"A:iVM3Ro;!O'H@rrgMCs)P.=rrg,Cs(Ae8rr=,;rrMj@o`#$m+2V4\rrITArr3"HU&P&nhI3>\
-rrVG(_X.:(jbC#[email protected]($+6gRf<<h/b%4\rVm!Equ<[:qYp\MS,`M0q#:PqG,("4kUHK1
-!CGN<rs)QFs6>F?KUDc=!RaX1rrHW@rr3#'D#XG9rb/]js+13$s5<p-~>
-"A:iVM3Ro;!O'H@rrgMCs)P.=rrg,Cs(Ae8rr=,;rrMj@o`#$m+2V4\rrITArr3"HU&P&nhI3>\
-rrVG(_X.:(jbC#[email protected]($+6gRf<<h/b%4\rVm!Equ<[:qYp\MS,`M0q#:PqG,("4kUHK1
-!CGN<rs)QFs6>F?KUDc=!RaX1rrHW@rr3#'D#XG9rb/]js+13$s5<p-~>
-"A:iVM'r6h"*ae$E;i3->g`RlWrE#$^g6ulB)Y-tHN*pIEC1"!K)YcQBL)tmMtR)OX^KZXrrL26
-r^-^;k5PA^aT->ZrrLn@lMgmTJH#QLq5"!W"d:Fsh_(&j6Na7`oU5YF"K_V&WcIt9"Q"/d6bE-n%
-HrJ%lcE#Es8S]Y&NNhhrs-tX6W;80KUDc=!RaX1rrL\]r^-^"f`(mOrZ?^kJcC<$huA3~>
-"A:iVM'r6h"*ae$E;i3->g`RlWrE#$^g6ulB)Y-tHN*pIEC1"!K)YcQBL)tmMtR)OX^KZXrrL26
-r^-^;k5PA^aT->ZrrLn@lMgmTJH#QLq5"!W"d:Fsh_(&j6Na7`oU5YF"K_V&WcIt9"Q"/d6bE-n%
-HrJ%lcE#Es8S]Y&NNhhrs-tX6W;80KUDc=!RaX1rrL\]r^-^"f`(mOrZ?^kJcC<$huA3~>
-"A:iVM'r6h"*ae$E;i3->g`RlWrE#$^g6ulB)Y-tHN*pIEC1"!K)YcQBL)tmMtR)OX^KZXrrL26
-r^-^;k5PA^aT->ZrrLn@lMgmTJH#QLq5"!W"d:Fsh_(&j6Na7`oU5YF"K_V&WcIt9"Q"/d6bE-n%
-HrJ%lcE#Es8S]Y&NNhhrs-tX6W;80KUDc=!RaX1rrL\]r^-^"f`(mOrZ?^kJcC<$huA3~>
-"%t`Umek`?jT#8Drn.G5s8VBUrr3,pkPtSCrn.;4rr2uYrn.;6rr2uWrn.;8p&>'hir&fVh#>t,
-mJ[%dpY"j1rrMuVlMgqTJ#rYL!;QQH"nL[MqW%/Gf`V$Ls7H9C"T&/uoBQ/O"6eFkrV-<pmdL2U
-hZ!NTm/GZ<h>I9Win<2gs6]=TrrMoUn,ECKrn.;5rVlm_hLY]Xs+14-s*t~>
-"%t`Umek`?jT#8Drn.G5s8VBUrr3,pkPtSCrn.;4rr2uYrn.;6rr2uWrn.;8p&>'hir&fVh#>t,
-mJ[%dpY"j1rrMuVlMgqTJ#rYL!;QQH"nL[MqW%/Gf`V$Ls7H9C"T&/uoBQ/O"6eFkrV-<pmdL2U
-hZ!NTm/GZ<h>I9Win<2gs6]=TrrMoUn,ECKrn.;5rVlm_hLY]Xs+14-s*t~>
-"%t`Umek`?jT#8Drn.G5s8VBUrr3,pkPtSCrn.;4rr2uYrn.;6rr2uWrn.;8p&>'hir&fVh#>t,
-mJ[%dpY"j1rrMuVlMgqTJ#rYL!;QQH"nL[MqW%/Gf`V$Ls7H9C"T&/uoBQ/O"6eFkrV-<pmdL2U
-hZ!NTm/GZ<h>I9Win<2gs6]=TrrMoUn,ECKrn.;5rVlm_hLY]Xs+14-s*t~>
-!D>M>rrN#pQ2^jZJcC<$JcFU,J,~>
-!D>M>rrN#pQ2^jZJcC<$JcFU,J,~>
-!D>M>rrN#pQ2^jZJcC<$JcFU,J,~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>NQrrK"krVlo0ipm$KT)JZh\GVHh_h%i=s+13$s/Z0M~>
-!D>NQrrK"krVlo0ipm$KT)JZh\GVHh_h%i=s+13$s/Z0M~>
-!D>NQrrK"krVlo0ipm$KT)JZh\GVHh_h%i=s+13$s/Z0M~>
-!D>NRrrSc-mJ[%d[sIB4rsbK>%<J'>s0[duMN!M0JcC<$JcC<$X8d\~>
-!D>NRrrSc-mJ[%d[sIB4rsbK>%<J'>s0[duMN!M0JcC<$JcC<$X8d\~>
-!D>NRrrSc-mJ[%d[sIB4rsbK>%<J'>s0[duMN!M0JcC<$JcC<$X8d\~>
-#>7/Ys.,5omJQtc^LI'5rsP9XW>)=oS,`M<TDjEAJcC<$JcD\KJ,~>
-#>7/Ys.,5omJQtc^LI'5rsP9XW>)=oS,`M<TDjEAJcC<$JcD\KJ,~>
-#>7/Ys.,5omJQtc^LI'5rsP9XW>)=oS,`M<TDjEAJcC<$JcD\KJ,~>
-#>7/YUPnOomJHnacVF36$>6gI*rkZbs8P:?JcC<$JcC<$VuM8~>
-#>7/YUPnOomJHnacVF36$>6gI*rkZbs8P:?JcC<$JcC<$VuM8~>
-#>7/YUPnOomJHnacVF36$>6gI*rkZbs8P:?JcC<$JcC<$VuM8~>
-#>7/YoCW&:mJ?h`dn0<6"RfFC*W>s:"6h]b:P&Oss+13$s/H$K~>
-#>7/YoCW&:mJ?h`dn0<6"RfFC*W>s:"6h]b:P&Oss+13$s/H$K~>
-#>7/YoCW&:mJ?h`dn0<6"RfFC*W>s:"6h]b:P&Oss+13$s/H$K~>
-!D>NQrrFh@qYpTB:A+Vm7Kc'As8V@[j+75]s+13$s/5mI~>
-!D>NQrrFh@qYpTB:A+Vm7Kc'As8V@[j+75]s+13$s/5mI~>
-!D>NQrrFh@qYpTB:A+Vm7Kc'As8V@[j+75]s+13$s/5mI~>
-!D>NQrrFh@qu6]>;Y0nm*o1A]s'3Bks+13$s+13Is*t~>
-!D>NQrrFh@qu6]>;Y0nm*o1A]s'3Bks+13$s+13Is*t~>
-!D>NQrrFh@qu6]>;Y0nm*o1A]s'3Bks+13$s+13Is*t~>
-!D>NQrrFh@r;Qi1B);6$$-D</*riT\s'3D9rrW+o]Rg*6s+13$s0;TS~>
-!D>NQrrFh@r;Qi1B);6$$-D</*riT\s'3D9rrW+o]Rg*6s+13$s0;TS~>
-!D>NQrrFh@r;Qi1B);6$$-D</*riT\s'3D9rrW+o]Rg*6s+13$s0;TS~>
-%SJn`a+f<dI>4^#s0R1?p&>?%JqahkK!>9SKDpT*YPnJ&pAdU4s+13$s+13Ts*t~>
-%SJn`a+f<dI>4^#s0R1?p&>?%JqahkK!>9SKDpT*YPnJ&pAdU4s+13$s+13Ts*t~>
-%SJn`a+f<dI>4^#s0R1?p&>?%JqahkK!>9SKDpT*YPnJ&pAdU4s+13$s+13Ts*t~>
-"%t`UcMWt2ZiC'>jR`BS[$D;i[Jp1+Yl9phLTURU!rS@iJcC<$JcC<$Z2]=~>
-"%t`UcMWt2ZiC'>jR`BS[$D;i[Jp1+Yl9phLTURU!rS@iJcC<$JcC<$Z2]=~>
-"%t`UcMWt2ZiC'>jR`BS[$D;i[Jp1+Yl9phLTURU!rS@iJcC<$JcC<$Z2]=~>
-!D>N9rrBb-rrK*@JcC<$JcC<$X8d\~>
-!D>N9rrBb-rrK*@JcC<$JcC<$X8d\~>
-!D>N9rrBb-rrK*@JcC<$JcC<$X8d\~>
-!D>N1rr_L<A`eRDJcC<$JcDeNJ,~>
-!D>N1rr_L<A`eRDJcC<$JcDeNJ,~>
-!D>N1rr_L<A`eRDJcC<$JcDeNJ,~>
-!D>N1rrW/foR[$ns+13$s/Q*L~>
-!D>N1rrW/foR[$ns+13$s/Q*L~>
-!D>N1rrW/foR[$ns+13$s/Q*L~>
-"A:iVs5s=1"5EkUl29$2ir8rZh:1/0s+13$s+13<s*t~>
-"A:iVs5s=1"5EkUl29$2ir8rZh:1/0s+13$s+13<s*t~>
-"A:iVs5s=1"5EkUl29$2ir8rZh:1/0s+13$s+13<s*t~>
-"A:iVh08ih"Bs"KI4bCg#D<'VcX9:FaasJCs+13$s-it<~>
-"A:iVh08ih"Bs"KI4bCg#D<'VcX9:FaasJCs+13$s-it<~>
-"A:iVh08ih"Bs"KI4bCg#D<'VcX9:FaasJCs+13$s-it<~>
-"A:iVM3S#>"P-'BI@pE:#01rEs6Fa?JcC<$JcC<$S,\!~>
-"A:iVM3S#>"P-'BI@pE:#01rEs6Fa?JcC<$JcC<$S,\!~>
-"A:iVM3S#>"P-'BI@pE:#01rEs6Fa?JcC<$JcC<$S,\!~>
-"A:iVM3S#>&_9GOI@m*XH^=^3]7/f?mX;?ks+13$s+13>s*t~>
-"A:iVM3S#>&_9GOI@m*XH^=^3]7/f?mX;?ks+13$s+13>s*t~>
-"A:iVM3S#>&_9GOI@m*XH^=^3]7/f?mX;?ks+13$s+13>s*t~>
-(eZsjM3S&?peOBZI63OaTp(Z>s1iGWB=NNmJcC<$JcD2=J,~>
-(eZsjM3S&?peOBZI63OaTp(Z>s1iGWB=NNmJcC<$JcD2=J,~>
-(eZsjM3S&?peOBZI63OaTp(Z>s1iGWB=NNmJcC<$JcD2=J,~>
-(eZsjiH7CN7\E6NhS8LYs3"=?s+$lZY&JslJcC<$JcD2=J,~>
-(eZsjiH7CN7\E6NhS8LYs3"=?s+$lZY&JslJcC<$JcD2=J,~>
-(eZsjiH7CN7\E6NhS8LYs3"=?s+$lZY&JslJcC<$JcD2=J,~>
-#tmA[s6JIqhUY0nrs?kHs+R*>s8&m>JcC<$JcC<$S,\!~>
-#tmA[s6JIqhUY0nrs?kHs+R*>s8&m>JcC<$JcC<$S,\!~>
-#tmA[s6JIqhUY0nrs?kHs+R*>s8&m>JcC<$JcC<$S,\!~>
-!D>NPrrrDA=TA!drr3;J;ZD6@qZ$K"Ck;V;s+13$s-s%=~>
-!D>NPrrrDA=TA!drr3;J;ZD6@qZ$K"Ck;V;s+13$s-s%=~>
-!D>NPrrrDA=TA!drr3;J;ZD6@qZ$K"Ck;V;s+13$s-s%=~>
-$qi\^s5;#@_cHg;R?IQk#ci.Ks*1Qc[V16lJcC<$JcD2=J,~>
-$qi\^s5;#@_cHg;R?IQk#ci.Ks*1Qc[V16lJcC<$JcD2=J,~>
-$qi\^s5;#@_cHg;R?IQk#ci.Ks*1Qc[V16lJcC<$JcD2=J,~>
-#>7/Ys-lqc>Q+R%Pl=S]G5_FBGZ/@.s+13$s+13<s*t~>
-#>7/Ys-lqc>Q+R%Pl=S]G5_FBGZ/@.s+13$s+13<s*t~>
-#>7/Ys-lqc>Q+R%Pl=S]G5_FBGZ/@.s+13$s+13<s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-"A:iVrHeGa#!r.ds)PpSp&>3n>ok%TqqqDSq^h^f!K[21s+13$s+13ns*t~>
-"A:iVrHeGa#!r.ds)PpSp&>3n>ok%TqqqDSq^h^f!K[21s+13$s+13ns*t~>
-"A:iVrHeGa#!r.ds)PpSp&>3n>ok%TqqqDSq^h^f!K[21s+13$s+13ns*t~>
-"A:iVM3S#>!S0a>rrQHBrq??qB=@j?dS&Kt!DCl?rrJ._JcC<$JcC<$bQ!(~>
-"A:iVM3S#>!S0a>rrQHBrq??qB=@j?dS&Kt!DCl?rrJ._JcC<$JcC<$bQ!(~>
-"A:iVM3S#>!S0a>rrQHBrq??qB=@j?dS&Kt!DCl?rrJ._JcC<$JcC<$bQ!(~>
-#tmA[Vm$.#r2Oo<rrHB@pAYG3[f?BU9E5%Cn,E=fl.l:<!64s:$./AAbQ$Y^s8U+<^B!*hrr<u:
-^B!3krrBk6^B!;Fs+13$s+13us*t~>
-#tmA[Vm$.#r2Oo<rrHB@pAYG3[f?BU9E5%Cn,E=fl.l:<!64s:$./AAbQ$Y^s8U+<^B!*hrr<u:
-^B!3krrBk6^B!;Fs+13$s+13us*t~>
-#tmA[Vm$.#r2Oo<rrHB@pAYG3[f?BU9E5%Cn,E=fl.l:<!64s:$./AAbQ$Y^s8U+<^B!*hrr<u:
-^B!3krrBk6^B!;Fs+13$s+13us*t~>
-!D>NPrrJs@qu6\1[.jS,B60c?KhMIG>f$F>!NC2?rr=,<rs;-HlS8F'MZ:+rra#_Uf`/6dra#_X
-h#FNara#VXi.:oZs+13$s3q!u~>
-!D>NPrrJs@qu6\1[.jS,B60c?KhMIG>f$F>!NC2?rr=,<rs;-HlS8F'MZ:+rra#_Uf`/6dra#_X
-h#FNara#VXi.:oZs+13$s3q!u~>
-!D>NPrrJs@qu6\1[.jS,B60c?KhMIG>f$F>!NC2?rr=,<rs;-HlS8F'MZ:+rra#_Uf`/6dra#_X
-h#FNara#VXi.:oZs+13$s3q!u~>
-!D>NQrrJU@qYpT[2#%"[B39M-AkW1(X+Kg?jFOf>rr=,<rs;-HlS8F'MZ5`trr3+VQ2`K)rr3+K
-U&QA5rr3#-e:IXNs+13$s3q!u~>
-!D>NQrrJU@qYpT[2#%"[B39M-AkW1(X+Kg?jFOf>rr=,<rs;-HlS8F'MZ5`trr3+VQ2`K)rr3+K
-U&QA5rr3#-e:IXNs+13$s3q!u~>
-!D>NQrrJU@qYpT[2#%"[B39M-AkW1(X+Kg?jFOf>rr=,<rs;-HlS8F'MZ5`trr3+VQ2`K)rr3+K
-U&QA5rr3#-e:IXNs+13$s3q!u~>
-!D>NRrrSFGq"k!kDm&j7"_Y:Ds3aR>rrbOCs2S1=rr=,<rs;-HlS8F'MZ5`trr3+VQ2`K)rr34N
-U&V$'AnJ&os+13$s+13ts*t~>
-!D>NRrrSFGq"k!kDm&j7"_Y:Ds3aR>rrbOCs2S1=rr=,<rs;-HlS8F'MZ5`trr3+VQ2`K)rr34N
-U&V$'AnJ&os+13$s+13ts*t~>
-!D>NRrrSFGq"k!kDm&j7"_Y:Ds3aR>rrbOCs2S1=rr=,<rs;-HlS8F'MZ5`trr3+VQ2`K)rr34N
-U&V$'AnJ&os+13$s+13ts*t~>
-#"q&Xs-8l>qYpS+](Z.-B=@j?dS'T>"NXX/@F+oP!$;(<#t<M41&mGps#T3>rre+Bs"<a=rs*qF
-s'i@E\(?32JcC<$JcF-tJ,~>
-#"q&Xs-8l>qYpS+](Z.-B=@j?dS'T>"NXX/@F+oP!$;(<#t<M41&mGps#T3>rre+Bs"<a=rs*qF
-s'i@E\(?32JcC<$JcF-tJ,~>
-#"q&Xs-8l>qYpS+](Z.-B=@j?dS'T>"NXX/@F+oP!$;(<#t<M41&mGps#T3>rre+Bs"<a=rs*qF
-s'i@E\(?32JcC<$JcF-tJ,~>
-"\UrWSW34:rrQZBrq??qB=@j?dS'Q=![-G]r;R9Ks2TNes$bT+1&mGps#T3>rre+Bs"<a=rrd_C
-s!.@=rrItfrr3&A/!>J`JcC<$JcFF'J,~>
-"\UrWSW34:rrQZBrq??qB=@j?dS'Q=![-G]r;R9Ks2TNes$bT+1&mGps#T3>rre+Bs"<a=rrd_C
-s!.@=rrItfrr3&A/!>J`JcC<$JcFF'J,~>
-"\UrWSW34:rrQZBrq??qB=@j?dS'Q=![-G]r;R9Ks2TNes$bT+1&mGps#T3>rre+Bs"<a=rrd_C
-s!.@=rrItfrr3&A/!>J`JcC<$JcFF'J,~>
-"A:iVO;Rp;"^M*-EkD;Crrr.#*Zd]BrVlrj2YI"J&*t?<p](9d4rX\IGkqC42?"X"Jbf?</H-[n
-MYdAE,5rVaPl(I[!l>M%JcC<$JcC<$g&HR~>
-"A:iVO;Rp;"^M*-EkD;Crrr.#*Zd]BrVlrj2YI"J&*t?<p](9d4rX\IGkqC42?"X"Jbf?</H-[n
-MYdAE,5rVaPl(I[!l>M%JcC<$JcC<$g&HR~>
-"A:iVO;Rp;"^M*-EkD;Crrr.#*Zd]BrVlrj2YI"J&*t?<p](9d4rX\IGkqC42?"X"Jbf?</H-[n
-MYdAE,5rVaPl(I[!l>M%JcC<$JcC<$g&HR~>
-!D>N"rrMF?JcC<$JcC<$\Gq'~>
-!D>N"rrMF?JcC<$JcC<$\Gq'~>
-!D>N"rrMF?JcC<$JcC<$\Gq'~>
-!D>N"rrMF?JcC<$JcC<$\Gq'~>
-!D>N"rrMF?JcC<$JcC<$\Gq'~>
-!D>N"rrMF?JcC<$JcC<$\Gq'~>
-!D>N"rrM_GJcC<$JcC<$\Gq'~>
-!D>N"rrM_GJcC<$JcC<$\Gq'~>
-!D>N"rrM_GJcC<$JcC<$\Gq'~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>NQrrIH;oD\f.li.!"FSu.?F^'4jrrR%AK'!"7oNPOlmf*=XI"D<Ks+13$s7QDB~>
-!D>NQrrIH;oD\f.li.!"FSu.?F^'4jrrR%AK'!"7oNPOlmf*=XI"D<Ks+13$s7QDB~>
-!D>NQrrIH;oD\f.li.!"FSu.?F^'4jrrR%AK'!"7oNPOlmf*=XI"D<Ks+13$s7QDB~>
-#tmA[V69hPmGN'ZrrHa>li."*b5D8@bH`l#rrU9A4lu\Gqn\)'mf*=Q1YMd/Qb7nLJcC<$TDsE~>
-#tmA[V69hPmGN'ZrrHa>li."*b5D8@bH`l#rrU9A4lu\Gqn\)'mf*=Q1YMd/Qb7nLJcC<$TDsE~>
-#tmA[V69hPmGN'ZrrHa>li."*b5D8@bH`l#rrU9A4lu\Gqn\)'mf*=Q1YMd/Qb7nLJcC<$TDsE~>
-#tmA[n8Punj$2c%rrQrD)WUhulS8;:!T6-$rrKH@mf*=Q1YMd/G,BijJcC<$TDsE~>
-#tmA[n8Punj$2c%rrQrD)WUhulS8;:!T6-$rrKH@mf*=Q1YMd/G,BijJcC<$TDsE~>
-#tmA[n8Punj$2c%rrQrD)WUhulS8;:!T6-$rrKH@mf*=Q1YMd/G,BijJcC<$TDsE~>
-#YR8Zs6a"o,j+k$"+miX*r>m;&MNhW!_OI]qu6]_1&LtOi'%&=!U2-6*XdYos6(XJ*d)V6s8)[8
-!L<EYrrKH@pAY0m`Vgh\YP[T:VZ%V=\GZBJr>l?_rRb34I3'HPs8TJ)*WsmkpmV.&$f1io*Y&i)
-*rl96M#JG%-KtK-K&fcM0C",gJcC<$ZN#F~>
-#YR8Zs6a"o,j+k$"+miX*r>m;&MNhW!_OI]qu6]_1&LtOi'%&=!U2-6*XdYos6(XJ*d)V6s8)[8
-!L<EYrrKH@pAY0m`Vgh\YP[T:VZ%V=\GZBJr>l?_rRb34I3'HPs8TJ)*WsmkpmV.&$f1io*Y&i)
-*rl96M#JG%-KtK-K&fcM0C",gJcC<$ZN#F~>
-#YR8Zs6a"o,j+k$"+miX*r>m;&MNhW!_OI]qu6]_1&LtOi'%&=!U2-6*XdYos6(XJ*d)V6s8)[8
-!L<EYrrKH@pAY0m`Vgh\YP[T:VZ%V=\GZBJr>l?_rRb34I3'HPs8TJ)*WsmkpmV.&$f1io*Y&i)
-*rl96M#JG%-KtK-K&fcM0C",gJcC<$ZN#F~>
-#tmA[j`JBojA4A"rr=,:rrGJko`"sd-N!fDlS8;:!T6->rrFb?rr37OU&QA5s8S+>qYpS-\,QC.
-ZYK46!VIi=rrd2tl3hh8rrG+?qu6sSnGfp5T`>$9qtpBq*rio]rVljnrr3"BVZ$MqVKVt=$1o\H
-s*Z-8s6):js+13$s0DZT~>
-#tmA[j`JBojA4A"rr=,:rrGJko`"sd-N!fDlS8;:!T6->rrFb?rr37OU&QA5s8S+>qYpS-\,QC.
-ZYK46!VIi=rrd2tl3hh8rrG+?qu6sSnGfp5T`>$9qtpBq*rio]rVljnrr3"BVZ$MqVKVt=$1o\H
-s*Z-8s6):js+13$s0DZT~>
-#tmA[j`JBojA4A"rr=,:rrGJko`"sd-N!fDlS8;:!T6->rrFb?rr37OU&QA5s8S+>qYpS-\,QC.
-ZYK46!VIi=rrd2tl3hh8rrG+?qu6sSnGfp5T`>$9qtpBq*rio]rVljnrr3"BVZ$MqVKVt=$1o\H
-s*Z-8s6):js+13$s0DZT~>
-#tmA[Z+0ffmGruorr=,+rrMj@qu6]_1&LtOi'%&=!A9uCW=)Uts!.@>s,N->s8Dnq!CO?qrrKH@
-pAY0d-i<oEl8/D="$#BAlM[[b*q93<BE%o5D#F=nrM]l7s1Mh9rrI;?rVlnq:B%4!U+--BI@pQ>
-n9BNaJcC<$ZN#F~>
-#tmA[Z+0ffmGruorr=,+rrMj@qu6]_1&LtOi'%&=!A9uCW=)Uts!.@>s,N->s8Dnq!CO?qrrKH@
-pAY0d-i<oEl8/D="$#BAlM[[b*q93<BE%o5D#F=nrM]l7s1Mh9rrI;?rVlnq:B%4!U+--BI@pQ>
-n9BNaJcC<$ZN#F~>
-#tmA[Z+0ffmGruorr=,+rrMj@qu6]_1&LtOi'%&=!A9uCW=)Uts!.@>s,N->s8Dnq!CO?qrrKH@
-pAY0d-i<oEl8/D="$#BAlM[[b*q93<BE%o5D#F=nrM]l7s1Mh9rrI;?rVlnq:B%4!U+--BI@pQ>
-n9BNaJcC<$ZN#F~>
-!D>NQrrJ/QoD\e3li."[-N!fDlS8;:!T6->rrF`grGr=hs+cMkN.JhFs-EV)!A:k\rrKH@pAY0d
--i<oEl8/D="$#B2LAc/r'_).2BDhc1k(N\S!tkRH@/9g'G,G6<!N%dREs.C#s*^Mjs+13$s/uBP~>
-!D>NQrrJ/QoD\e3li."[-N!fDlS8;:!T6->rrF`grGr=hs+cMkN.JhFs-EV)!A:k\rrKH@pAY0d
--i<oEl8/D="$#B2LAc/r'_).2BDhc1k(N\S!tkRH@/9g'G,G6<!N%dREs.C#s*^Mjs+13$s/uBP~>
-!D>NQrrJ/QoD\e3li."[-N!fDlS8;:!T6->rrF`grGr=hs+cMkN.JhFs-EV)!A:k\rrKH@pAY0d
--i<oEl8/D="$#B2LAc/r'_).2BDhc1k(N\S!tkRH@/9g'G,G6<!N%dREs.C#s*^Mjs+13$s/uBP~>
-!D>NArr=,:rrI;!o`"sd-N!fDlS8;:!T6->rrFb?qu6eNOHG[Brr2s>rr3&1/@YWY!OHP7rrMd?
-rVltal0:)'rrY7Ah`h&>"dftms0cS<rrL2@rr3+[&c]OPrVlkIrr34HVZ6[Gs/'u9rrIP?JcC<$
-JcDnQJ,~>
-!D>NArr=,:rrI;!o`"sd-N!fDlS8;:!T6->rrFb?qu6eNOHG[Brr2s>rr3&1/@YWY!OHP7rrMd?
-rVltal0:)'rrY7Ah`h&>"dftms0cS<rrL2@rr3+[&c]OPrVlkIrr34HVZ6[Gs/'u9rrIP?JcC<$
-JcDnQJ,~>
-!D>NArr=,:rrI;!o`"sd-N!fDlS8;:!T6->rrFb?qu6eNOHG[Brr2s>rr3&1/@YWY!OHP7rrMd?
-rVltal0:)'rrY7Ah`h&>"dftms0cS<rrL2@rr3+[&c]OPrVlkIrr34HVZ6[Gs/'u9rrIP?JcC<$
-JcDnQJ,~>
-!D>NDrs#)m;$g)sOT#1[%P@AR"ER<H;3V"Z"Dg[A;4IRb#\6F=;54*j]iY21"KMM%\l8T*"1%t,
-[/No/IRUaGo2.Lk;8N&-!W8Vh;$3-Ul8/D="$#B7R/TqdP99;o[V,O<!Uc$J;$<@(s6>O@;#mj"
-rs.%n;,Ok'j+I>.!*K7#!I^Sks+13$s/uBP~>
-!D>NDrs#)m;$g)sOT#1[%P@AR"ER<H;3V"Z"Dg[A;4IRb#\6F=;54*j]iY21"KMM%\l8T*"1%t,
-[/No/IRUaGo2.Lk;8N&-!W8Vh;$3-Ul8/D="$#B7R/TqdP99;o[V,O<!Uc$J;$<@(s6>O@;#mj"
-rs.%n;,Ok'j+I>.!*K7#!I^Sks+13$s/uBP~>
-!D>NDrs#)m;$g)sOT#1[%P@AR"ER<H;3V"Z"Dg[A;4IRb#\6F=;54*j]iY21"KMM%\l8T*"1%t,
-[/No/IRUaGo2.Lk;8N&-!W8Vh;$3-Ul8/D="$#B7R/TqdP99;o[V,O<!Uc$J;$<@(s6>O@;#mj"
-rs.%n;,Ok'j+I>.!*K7#!I^Sks+13$s/uBP~>
-!D>NDrrD*WbQ-Q!rrLHrp&>$CrlbB"rr2uJrlbB%rr2uHrlbB'rr2uErlbN-s8Pm:rlbIg^&S*2
-bQR%cnc/OcbQ.&)rrDflbQID8qpt`G"5!DLoDZr;nC@I:nDX9E!:Kj1"SL4Cs6T^.!<)lr!oD/F
-rr2u]rlbAfrr3#\m",1fs+13Qs*t~>
-!D>NDrrD*WbQ-Q!rrLHrp&>$CrlbB"rr2uJrlbB%rr2uHrlbB'rr2uErlbN-s8Pm:rlbIg^&S*2
-bQR%cnc/OcbQ.&)rrDflbQID8qpt`G"5!DLoDZr;nC@I:nDX9E!:Kj1"SL4Cs6T^.!<)lr!oD/F
-rr2u]rlbAfrr3#\m",1fs+13Qs*t~>
-!D>NDrrD*WbQ-Q!rrLHrp&>$CrlbB"rr2uJrlbB%rr2uHrlbB'rr2uErlbN-s8Pm:rlbIg^&S*2
-bQR%cnc/OcbQ.&)rrDflbQID8qpt`G"5!DLoDZr;nC@I:nDX9E!:Kj1"SL4Cs6T^.!<)lr!oD/F
-rr2u]rlbAfrr3#\m",1fs+13Qs*t~>
-!D>MarrFV?rq?G6YCZ_)s+13$s3q!u~>
-!D>MarrFV?rq?G6YCZ_)s+13$s3q!u~>
-!D>MarrFV?rq?G6YCZ_)s+13$s3q!u~>
-!D>M`rr=PJ-30Zhs+13$s+13us*t~>
-!D>M`rr=PJ-30Zhs+13$s+13us*t~>
-!D>M`rr=PJ-30Zhs+13$s+13us*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-"A:iVs2Y,1!3Z>$!Q4&Ns+13$s+132s*t~>
-"A:iVs2Y,1!3Z>$!Q4&Ns+13$s+132s*t~>
-"A:iVs2Y,1!3Z>$!Q4&Ns+13$s+132s*t~>
-"A:iV`..c8#(NHKs0$t?JcC<$JcC<$OT0h~>
-"A:iV`..c8#(NHKs0$t?JcC<$JcC<$OT0h~>
-"A:iV`..c8#(NHKs0$t?JcC<$JcC<$OT0h~>
-"A:iVM3S#>!S0a>rrTTDqgncus+13$s,m>3~>
-"A:iVM3S#>!S0a>rrTTDqgncus+13$s,m>3~>
-"A:iVM3S#>!S0a>rrTTDqgncus+13$s,m>3~>
-#tmA[hr=\9pK5Z<rrL#?JcC<$JcC<$OoKq~>
-#tmA[hr=\9pK5Z<rrL#?JcC<$JcC<$OoKq~>
-#tmA[hr=\9pK5Z<rrL#?JcC<$JcC<$OoKq~>
-!D>NPrrG@?qu6]<<.Y(#s+13$s-!D4~>
-!D>NPrrG@?qu6]<<.Y(#s+13$s-!D4~>
-!D>NPrrG@?qu6]<<.Y(#s+13$s-!D4~>
-!D>NRrrVaZjneuXg-^GkJcC<$JcCo5J,~>
-!D>NRrrVaZjneuXg-^GkJcC<$JcCo5J,~>
-!D>NRrrVaZjneuXg-^GkJcC<$JcCo5J,~>
-#"q&Xs5RM>qYpTI7tL\ks+13$s,m>3~>
-#"q&Xs5RM>qYpTI7tL\ks+13$s,m>3~>
-#"q&Xs5RM>qYpTI7tL\ks+13$s,m>3~>
-"\UrWgN^j:rrU/EqLSZts+13$s,m>3~>
-"\UrWgN^j:rrU/EqLSZts+13$s,m>3~>
-"\UrWgN^j:rrU/EqLSZts+13$s,m>3~>
-"A:iVM,sS>"gS+-]QWRks+13$s+133s*t~>
-"A:iVM,sS>"gS+-]QWRks+13$s+133s*t~>
-"A:iVM,sS>"gS+-]QWRks+13$s+133s*t~>
-"%t`UaS^ktWrN+,i.:oZs+13$s,[21~>
-"%t`UaS^ktWrN+,i.:oZs+13$s,[21~>
-"%t`UaS^ktWrN+,i.:oZs+13$s,[21~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-!D>M*s+13$s+13&s*t~>
-%%EndData
-showpage
-%%Trailer
-end
-%%EOF
diff --git a/lib/stdlib/doc/src/ushell3.gif b/lib/stdlib/doc/src/ushell3.gif
deleted file mode 100644
index 2141268b91..0000000000
--- a/lib/stdlib/doc/src/ushell3.gif
+++ /dev/null
Binary files differ
diff --git a/lib/stdlib/doc/src/ushell3.ps b/lib/stdlib/doc/src/ushell3.ps
deleted file mode 100644
index dd64eeab5c..0000000000
--- a/lib/stdlib/doc/src/ushell3.ps
+++ /dev/null
@@ -1,662 +0,0 @@
-%!PS-Adobe-3.0
-%%Creator: GIMP PostScript file plugin V 1.17 by Peter Kirchgessner
-%%Title: ushell3.ps
-%%CreationDate: Mon Mar 16 12:15:17 2009
-%%DocumentData: Clean7Bit
-%%LanguageLevel: 2
-%%Pages: 1
-%%BoundingBox: 14 14 468 78
-%%EndComments
-%%BeginProlog
-% Use own dictionary to avoid conflicts
-10 dict begin
-%%EndProlog
-%%Page: 1 1
-% Translate for offset
-14.173228346456694 14.173228346456694 translate
-% Translate to begin of first scanline
-0 63.070866141732289 translate
-453.54330708661422 -63.070866141732289 scale
-% Image geometry
-640 89 8
-% Transformation matrix
-[ 640 0 0 89 0 0 ]
-% Strings to hold RGB-samples per scanline
-/rstr 640 string def
-/gstr 640 string def
-/bstr 640 string def
-{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop}
-{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop}
-{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop}
-true 3
-%%BeginData: 37475 ASCII Bytes
-colorimage
-!1\W%J`VIEJ`VLFJ,~>
-!1\W%J`VIEJ`VLFJ,~>
-!1\W%J`VIEJ`VLFJ,~>
-!T[+/6@hIS6@hIU6@]~>
-!T[+/6@hIS6@hIU6@]~>
-!T[+/6@hIS6@hIU6@]~>
-!ouWfJQ.2"JQ.2"KN*I~>
-!ouWfJQ.2"JQ.2"KN*I~>
-!ouWfJQ.2"JQ.2"KN*I~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLQ2^m!`0L?'S`PG&JcC<$i;\<~>
-!ouXLQ2^m!`0L?'S`PG&JcC<$i;\<~>
-!ouXLQ2^m!`0L?'S`PG&JcC<$i;\<~>
-"QVjNs.9-i!1*E[!L)+*rrR=EF8Z%>Dc_2VrrI?7rr3)%^&N-N<rg/5rr?^0<rgP6rrU,eg\:^K
-o6/O]!ioDNpAY05U[\9aJa!(4!2BHo!,VW6!lAR@JcC<$JcF^/J,~>
-"QVjNs.9-i!1*E[!L)+*rrR=EF8Z%>Dc_2VrrI?7rr3)%^&N-N<rg/5rr?^0<rgP6rrU,eg\:^K
-o6/O]!ioDNpAY05U[\9aJa!(4!2BHo!,VW6!lAR@JcC<$JcF^/J,~>
-"QVjNs.9-i!1*E[!L)+*rrR=EF8Z%>Dc_2VrrI?7rr3)%^&N-N<rg/5rr?^0<rgP6rrU,eg\:^K
-o6/O]!ioDNpAY05U[\9aJa!(4!2BHo!,VW6!lAR@JcC<$JcF^/J,~>
-"lqsOs)!Pi_uSNdrrHB@o)Ad;\gmXX!mS).p&>%Ili-neJXl`h]D]YJlM1AZb5K6Z:po`k!N()7
-rrML@l2LdgT^2UZil(<`rrJFsrVlntF7K88K;)-<s8T'RrkniDCAn/50C=>jJcC<$iW"E~>
-"lqsOs)!Pi_uSNdrrHB@o)Ad;\gmXX!mS).p&>%Ili-neJXl`h]D]YJlM1AZb5K6Z:po`k!N()7
-rrML@l2LdgT^2UZil(<`rrJFsrVlntF7K88K;)-<s8T'RrkniDCAn/50C=>jJcC<$iW"E~>
-"lqsOs)!Pi_uSNdrrHB@o)Ad;\gmXX!mS).p&>%Ili-neJXl`h]D]YJlM1AZb5K6Z:po`k!N()7
-rrML@l2LdgT^2UZil(<`rrJFsrVlntF7K88K;)-<s8T'RrkniDCAn/50C=>jJcC<$iW"E~>
-"lqsOs)#"3rrHB@nc&X\.f95Hkqi#4!AWp>rrdnCs!dR.rrSCIp@&"_b$si5rrML@l2LdPK]E(5
-GGY9<!NC/2rs4ONpZ4C7s,`6>rrN#\rVlo\2M(mZs+14/s*t~>
-"lqsOs)#"3rrHB@nc&X\.f95Hkqi#4!AWp>rrdnCs!dR.rrSCIp@&"_b$si5rrML@l2LdPK]E(5
-GGY9<!NC/2rs4ONpZ4C7s,`6>rrN#\rVlo\2M(mZs+14/s*t~>
-"lqsOs)#"3rrHB@nc&X\.f95Hkqi#4!AWp>rrdnCs!dR.rrSCIp@&"_b$si5rrML@l2LdPK]E(5
-GGY9<!NC/2rs4ONpZ4C7s,`6>rrN#\rVlo\2M(mZs+14/s*t~>
-#in9Rs)"@hjludE!Us(f*"5s=s'2Za*#r;Ts6`DV*!'XArr3#i.f95Hkqi#4$2ktGs.=c>s!c4l
-*!(ffp&>*eKVIo7!Q/(<rrCjQ*!EJBm4518*!<VHr42bG&A7u":Z[6L*5hd.*"`Z#*8gPk!Q/1@
-rrsVGs/-hF]Dhg?\f;.l*$"qWWG$>m*$OSArs>H^rr<#^9E1*5p\t46JcC<$JcF^/J,~>
-#in9Rs)"@hjludE!Us(f*"5s=s'2Za*#r;Ts6`DV*!'XArr3#i.f95Hkqi#4$2ktGs.=c>s!c4l
-*!(ffp&>*eKVIo7!Q/(<rrCjQ*!EJBm4518*!<VHr42bG&A7u":Z[6L*5hd.*"`Z#*8gPk!Q/1@
-rrsVGs/-hF]Dhg?\f;.l*$"qWWG$>m*$OSArs>H^rr<#^9E1*5p\t46JcC<$JcF^/J,~>
-#in9Rs)"@hjludE!Us(f*"5s=s'2Za*#r;Ts6`DV*!'XArr3#i.f95Hkqi#4$2ktGs.=c>s!c4l
-*!(ffp&>*eKVIo7!Q/(<rrCjQ*!EJBm4518*!<VHr42bG&A7u":Z[6L*5hd.*"`Z#*8gPk!Q/1@
-rrsVGs/-hF]Dhg?\f;.l*$"qWWG$>m*$OSArs>H^rr<#^9E1*5p\t46JcC<$JcF^/J,~>
-#in9Rs(s&?2H0VT!G&_>rsZf$s'-u6s8T->s&7&=rrJm@rr3#i.f95Hkqhu3#T`sFSpp_><^Zld
-!I1F5rrJj?mJd4)=nhq!7G$o6ErQ(@4l><[rVm<akl8@2QiI(:nGiNVK_>?L_HQutn,FF,rrHT?
-r;QeAV>^DuW>MT6s7dl/rs"REs8UEef)5OJ*J+6As+14/s*t~>
-#in9Rs(s&?2H0VT!G&_>rsZf$s'-u6s8T->s&7&=rrJm@rr3#i.f95Hkqhu3#T`sFSpp_><^Zld
-!I1F5rrJj?mJd4)=nhq!7G$o6ErQ(@4l><[rVm<akl8@2QiI(:nGiNVK_>?L_HQutn,FF,rrHT?
-r;QeAV>^DuW>MT6s7dl/rs"REs8UEef)5OJ*J+6As+14/s*t~>
-#in9Rs(s&?2H0VT!G&_>rsZf$s'-u6s8T->s&7&=rrJm@rr3#i.f95Hkqhu3#T`sFSpp_><^Zld
-!I1F5rrJj?mJd4)=nhq!7G$o6ErQ(@4l><[rVm<akl8@2QiI(:nGiNVK_>?L_HQutn,FF,rrHT?
-r;QeAV>^DuW>MT6s7dl/rs"REs8UEef)5OJ*J+6As+14/s*t~>
-"lqsOs)#";rrJFMriH=Cs8Q??rr3,%EW8soriH3>HN*pFngaP:!U2E4rrciCl&)D8rrIA?pAY3[
-N2>qA!Q/(<rrDWgXTL6.m4eM="$PQ&3;rj[2<b(S?N0s.E:s82R=t85#/XRDCU3s\rVln-]);R/
-GGY9<!NC/>rrMm?nG`]SNW9#h7m6eM!$-XjJcC<$iW"E~>
-"lqsOs)#";rrJFMriH=Cs8Q??rr3,%EW8soriH3>HN*pFngaP:!U2E4rrciCl&)D8rrIA?pAY3[
-N2>qA!Q/(<rrDWgXTL6.m4eM="$PQ&3;rj[2<b(S?N0s.E:s82R=t85#/XRDCU3s\rVln-]);R/
-GGY9<!NC/>rrMm?nG`]SNW9#h7m6eM!$-XjJcC<$iW"E~>
-"lqsOs)#";rrJFMriH=Cs8Q??rr3,%EW8soriH3>HN*pFngaP:!U2E4rrciCl&)D8rrIA?pAY3[
-N2>qA!Q/(<rrDWgXTL6.m4eM="$PQ&3;rj[2<b(S?N0s.E:s82R=t85#/XRDCU3s\rVln-]);R/
-GGY9<!NC/>rrMm?nG`]SNW9#h7m6eM!$-XjJcC<$iW"E~>
-"lqsOs)#":rrAAaD?P3us'3D>rrfBBs&2tsD?.$BrrM[?qu6]]1\C\Lp*RC[q>UJ?V"Xfh^Kp4+
-!Q/(=rrN"UrGD]YfBk9jrrYFAj>d,<"?#EC^0^[9!L\W6rs$>Ds(eq?*W?!=@_2L;!I(C=rrK*?
-rr3#o,k1g7OH'8>!T-'<rr='js+13$s5F!.~>
-"lqsOs)#":rrAAaD?P3us'3D>rrfBBs&2tsD?.$BrrM[?qu6]]1\C\Lp*RC[q>UJ?V"Xfh^Kp4+
-!Q/(=rrN"UrGD]YfBk9jrrYFAj>d,<"?#EC^0^[9!L\W6rs$>Ds(eq?*W?!=@_2L;!I(C=rrK*?
-rr3#o,k1g7OH'8>!T-'<rr='js+13$s5F!.~>
-"lqsOs)#":rrAAaD?P3us'3D>rrfBBs&2tsD?.$BrrM[?qu6]]1\C\Lp*RC[q>UJ?V"Xfh^Kp4+
-!Q/(=rrN"UrGD]YfBk9jrrYFAj>d,<"?#EC^0^[9!L\W6rs$>Ds(eq?*W?!=@_2L;!I(C=rrK*?
-rr3#o,k1g7OH'8>!T-'<rr='js+13$s5F!.~>
-"lqsOs)#";rrK1Rrr3,.C&_GSrr3,%EW8tZq>UKd.f95Hkqhu3"84(R@K-9-Mu!AP!I1F>rrV/%
-Zi0n*m!?)+rrV55[Jp1,odBb="fictm1u>nrrYFAj>d,<"?#EC^0^[9"dt&Ds,$[Lrs$>D^O^an
-*W?!=@_2L;#C!$Es+UKPF8l1?pa#A/!K`<?rrM"?rVlnZNIh+\s+14/s*t~>
-"lqsOs)#";rrK1Rrr3,.C&_GSrr3,%EW8tZq>UKd.f95Hkqhu3"84(R@K-9-Mu!AP!I1F>rrV/%
-Zi0n*m!?)+rrV55[Jp1,odBb="fictm1u>nrrYFAj>d,<"?#EC^0^[9"dt&Ds,$[Lrs$>D^O^an
-*W?!=@_2L;#C!$Es+UKPF8l1?pa#A/!K`<?rrM"?rVlnZNIh+\s+14/s*t~>
-"lqsOs)#";rrK1Rrr3,.C&_GSrr3,%EW8tZq>UKd.f95Hkqhu3"84(R@K-9-Mu!AP!I1F>rrV/%
-Zi0n*m!?)+rrV55[Jp1,odBb="fictm1u>nrrYFAj>d,<"?#EC^0^[9"dt&Ds,$[Lrs$>D^O^an
-*W?!=@_2L;#C!$Es+UKPF8l1?pa#A/!K`<?rrM"?rVlnZNIh+\s+14/s*t~>
-"lqsOs(spt=Tb&ka`%/]"E;N`>f$F>"KQPB_eK*Q!1!Q`"F!iV=e#Ej"E@<P=ePKg"8nU*aSu2?
-ZsEZ6!J95.rrU7AErH"=gd(0)!N()?rrN%dr`KD\/_BA3O8`8aPP"R6rE08hp]%s6qYp`RIT]gC
-rV?I'lAL)E_.]YEs1_\\6!=!^rs-kl=]qs.WH8(=!Vdr0rrLc"r`K83]D_a10C=>jJcC<$iW"E~>
-"lqsOs(spt=Tb&ka`%/]"E;N`>f$F>"KQPB_eK*Q!1!Q`"F!iV=e#Ej"E@<P=ePKg"8nU*aSu2?
-ZsEZ6!J95.rrU7AErH"=gd(0)!N()?rrN%dr`KD\/_BA3O8`8aPP"R6rE08hp]%s6qYp`RIT]gC
-rV?I'lAL)E_.]YEs1_\\6!=!^rs-kl=]qs.WH8(=!Vdr0rrLc"r`K83]D_a10C=>jJcC<$iW"E~>
-"lqsOs(spt=Tb&ka`%/]"E;N`>f$F>"KQPB_eK*Q!1!Q`"F!iV=e#Ej"E@<P=ePKg"8nU*aSu2?
-ZsEZ6!J95.rrU7AErH"=gd(0)!N()?rrN%dr`KD\/_BA3O8`8aPP"R6rE08hp]%s6qYp`RIT]gC
-rV?I'lAL)E_.]YEs1_\\6!=!^rs-kl=]qs.WH8(=!Vdr0rrLc"r`K83]D_a10C=>jJcC<$iW"E~>
-"QVjNs4mOh"53_Se,I2eeGoR$nG`FjleVU@ci1c]f`(mNc2PQ[gA_*PbPo?Yh"C[Jp<rm=!6+rS
-!93tW!qO4arVlomdH^`5l@c>>rrDcl_?K,Np&!#$rk\d,s8VZg_?BH0s7"\:rr_/q_Y3a(#jL4G
-s3:H@s6'?t!<)lr#1p`/s8VB?rr3#tb4#?1h>Y7kb5M>AGH(Ijs+13$s5F!.~>
-"QVjNs4mOh"53_Se,I2eeGoR$nG`FjleVU@ci1c]f`(mNc2PQ[gA_*PbPo?Yh"C[Jp<rm=!6+rS
-!93tW!qO4arVlomdH^`5l@c>>rrDcl_?K,Np&!#$rk\d,s8VZg_?BH0s7"\:rr_/q_Y3a(#jL4G
-s3:H@s6'?t!<)lr#1p`/s8VB?rr3#tb4#?1h>Y7kb5M>AGH(Ijs+13$s5F!.~>
-"QVjNs4mOh"53_Se,I2eeGoR$nG`FjleVU@ci1c]f`(mNc2PQ[gA_*PbPo?Yh"C[Jp<rm=!6+rS
-!93tW!qO4arVlomdH^`5l@c>>rrDcl_?K,Np&!#$rk\d,s8VZg_?BH0s7"\:rr_/q_Y3a(#jL4G
-s3:H@s6'?t!<)lr#1p`/s8VB?rr3#tb4#?1h>Y7kb5M>AGH(Ijs+13$s5F!.~>
-!ouXLQ2^mSnWj+TkkTf0JcC<$i;\<~>
-!ouXLQ2^mSnWj+TkkTf0JcC<$i;\<~>
-!ouXLQ2^mSnWj+TkkTf0JcC<$i;\<~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcG]K!TNR]rr_0&bgEm!"4YQ=h#.0PdXhFLs/5mI~>
-!ouXLJcG]K!TNR]rr_0&bgEm!"4YQ=h#.0PdXhFLs/5mI~>
-!ouXLJcG]K!TNR]rr_0&bgEm!"4YQ=h#.0PdXhFLs/5mI~>
-!ouXLrVll.r;Qf;o()e]\@V&,!kGPPr;QirYf6S@!PSC#rr_SkYi""2!o&"@rVm>df)Ne\s8V;e
-g&M)arUBgji3;2?s1.k'"4H?3\b5t)>rthhrVluBmf'fsrr^ZQYd<0c!6"l@!6Y!7"1eHrci3qH
-Bhpuir;Qe$_L_`<s/>sJ~>
-!ouXLrVll.r;Qf;o()e]\@V&,!kGPPr;QirYf6S@!PSC#rr_SkYi""2!o&"@rVm>df)Ne\s8V;e
-g&M)arUBgji3;2?s1.k'"4H?3\b5t)>rthhrVluBmf'fsrr^ZQYd<0c!6"l@!6Y!7"1eHrci3qH
-Bhpuir;Qe$_L_`<s/>sJ~>
-!ouXLrVll.r;Qf;o()e]\@V&,!kGPPr;QirYf6S@!PSC#rr_SkYi""2!o&"@rVm>df)Ne\s8V;e
-g&M)arUBgji3;2?s1.k'"4H?3\b5t)>rthhrVluBmf'fsrr^ZQYd<0c!6"l@!6Y!7"1eHrci3qH
-Bhpuir;Qe$_L_`<s/>sJ~>
-!ouXLrr3"u(&\(5P`>P2rrICpm/I-7?T\2c!r?\qrVlmIoCDnbn;;!sKAbYe!T1]hrrJ(?r;RA&
-HiH[ds6YVXJCjfHq>^KAch7;Bie2*#ir:%mrr[/AruLe4!F<J;rsMiIr#l%>c$X;BD5H.i!P<LR
-CB8[tpAY48s0uV;rrLA?r;QfW3e@<^s/>sJ~>
-!ouXLrr3"u(&\(5P`>P2rrICpm/I-7?T\2c!r?\qrVlmIoCDnbn;;!sKAbYe!T1]hrrJ(?r;RA&
-HiH[ds6YVXJCjfHq>^KAch7;Bie2*#ir:%mrr[/AruLe4!F<J;rsMiIr#l%>c$X;BD5H.i!P<LR
-CB8[tpAY48s0uV;rrLA?r;QfW3e@<^s/>sJ~>
-!ouXLrr3"u(&\(5P`>P2rrICpm/I-7?T\2c!r?\qrVlmIoCDnbn;;!sKAbYe!T1]hrrJ(?r;RA&
-HiH[ds6YVXJCjfHq>^KAch7;Bie2*#ir:%mrr[/AruLe4!F<J;rsMiIr#l%>c$X;BD5H.i!P<LR
-CB8[tpAY48s0uV;rrLA?r;QfW3e@<^s/>sJ~>
-#NS0Qs8SgH'Dqe1RtBDp!T?-5rrFS?o)AmK5l^js[GUubZ>0::!n)SAr;RA&HiH[ds3jR>_1$W_
-r;ZeYN:m2T\mk]II!C_Grr[/AruLe4!F<J;rsMiIr#l%>LR%o>oI8\t#.&^Es8U`apAY48s0uV;
-rrLA?r;QigKVj>#JcD_LJ,~>
-#NS0Qs8SgH'Dqe1RtBDp!T?-5rrFS?o)AmK5l^js[GUubZ>0::!n)SAr;RA&HiH[ds3jR>_1$W_
-r;ZeYN:m2T\mk]II!C_Grr[/AruLe4!F<J;rsMiIr#l%>LR%o>oI8\t#.&^Es8U`apAY48s0uV;
-rrLA?r;QigKVj>#JcD_LJ,~>
-#NS0Qs8SgH'Dqe1RtBDp!T?-5rrFS?o)AmK5l^js[GUubZ>0::!n)SAr;RA&HiH[ds3jR>_1$W_
-r;ZeYN:m2T\mk]II!C_Grr[/AruLe4!F<J;rsMiIr#l%>LR%o>oI8\t#.&^Es8U`apAY48s0uV;
-rrLA?r;QigKVj>#JcD_LJ,~>
-#NS0Qs.PG>*W#d:UNuP4!e+Bor;QbBr`fGnp&>'O48f*[Bj?GlrrFS4r`fH/rVlrS>c%E!#M_TE
-s2a:$pAJ50_Z0XSs3"YPaT)6E>a;X#c2[h+rEKWWs79J\-<sg.rr3#!F8PtRh9c29n,Mjis8U'5
-o)IQO1br<@mf3=+rEKd&s5qB%s1G-(s3748r`fI&rr3)Dir?1SrrHE?qu72Dli+*fs+cm>s7@c?
-s/j-:rrM&<rr3"Nm/?qjU<NXUs4*P;s,-e\!/pjV"@#[e>`o$c!.XuQ!1*T`"0V[da8Gr<btn6:
-!QA,ks+13Ls*t~>
-#NS0Qs.PG>*W#d:UNuP4!e+Bor;QbBr`fGnp&>'O48f*[Bj?GlrrFS4r`fH/rVlrS>c%E!#M_TE
-s2a:$pAJ50_Z0XSs3"YPaT)6E>a;X#c2[h+rEKWWs79J\-<sg.rr3#!F8PtRh9c29n,Mjis8U'5
-o)IQO1br<@mf3=+rEKd&s5qB%s1G-(s3748r`fI&rr3)Dir?1SrrHE?qu72Dli+*fs+cm>s7@c?
-s/j-:rrM&<rr3"Nm/?qjU<NXUs4*P;s,-e\!/pjV"@#[e>`o$c!.XuQ!1*T`"0V[da8Gr<btn6:
-!QA,ks+13Ls*t~>
-#NS0Qs.PG>*W#d:UNuP4!e+Bor;QbBr`fGnp&>'O48f*[Bj?GlrrFS4r`fH/rVlrS>c%E!#M_TE
-s2a:$pAJ50_Z0XSs3"YPaT)6E>a;X#c2[h+rEKWWs79J\-<sg.rr3#!F8PtRh9c29n,Mjis8U'5
-o)IQO1br<@mf3=+rEKd&s5qB%s1G-(s3748r`fI&rr3)Dir?1SrrHE?qu72Dli+*fs+cm>s7@c?
-s/j-:rrM&<rr3"Nm/?qjU<NXUs4*P;s,-e\!/pjV"@#[e>`o$c!.XuQ!1*T`"0V[da8Gr<btn6:
-!QA,ks+13Ls*t~>
-#NS0Qs4Zf=*W#d;ql"c5rrUHX,5qNBGcC\W!KEfHrrM(?r;Qi:U."t[!@^M;^B&_orr3&@!-8&<
-!Sfs<rr>sq^CtP2s0b1+^V=R6rYN>5HbX4Is7Q?*#\)ch^P5S"^[V7&!NL5.rsA82Ch^Z!q#AcZ
-rP&>0q#:E#)he4*!*/Ie!F<J5rs=H,5X7I]s8RS?rr3#E:B(7o4Q68=$#ZsH*WNf[s,<HH^BC!c
-s+R-F^BBjes*pjD^B'Ldp&>';:](.m`E.WjJcD_LJ,~>
-#NS0Qs4Zf=*W#d;ql"c5rrUHX,5qNBGcC\W!KEfHrrM(?r;Qi:U."t[!@^M;^B&_orr3&@!-8&<
-!Sfs<rr>sq^CtP2s0b1+^V=R6rYN>5HbX4Is7Q?*#\)ch^P5S"^[V7&!NL5.rsA82Ch^Z!q#AcZ
-rP&>0q#:E#)he4*!*/Ie!F<J5rs=H,5X7I]s8RS?rr3#E:B(7o4Q68=$#ZsH*WNf[s,<HH^BC!c
-s+R-F^BBjes*pjD^B'Ldp&>';:](.m`E.WjJcD_LJ,~>
-#NS0Qs4Zf=*W#d;ql"c5rrUHX,5qNBGcC\W!KEfHrrM(?r;Qi:U."t[!@^M;^B&_orr3&@!-8&<
-!Sfs<rr>sq^CtP2s0b1+^V=R6rYN>5HbX4Is7Q?*#\)ch^P5S"^[V7&!NL5.rsA82Ch^Z!q#AcZ
-rP&>0q#:E#)he4*!*/Ie!F<J5rs=H,5X7I]s8RS?rr3#E:B(7o4Q68=$#ZsH*WNf[s,<HH^BC!c
-s+R-F^BBjes*pjD^B'Ldp&>';:](.m`E.WjJcD_LJ,~>
-!ouXLrVlj<q>UKC9D/;cqBGn<!DCl?rrJR?pAY0P48]$YfgPf=!@cOtrrIA?rr3&og["k="?7J0
-,`Vg'!$2%<&RW6Okq)#ts&R/=+9/3^s%^l:rrkjCs8TB>qu6\sF6ii,OGs/<!Q&%=rrCsOrrTH1
-mf*4d*U`q.?,-(4%YoShgX7PNs6XR>s6`D>rr3!]iVic_DQj'\s1Me>A[h[="LVqC?,6I>"KZSB
-<65(=!V5UMrrLA?qu6]9=+UC&s/H$K~>
-!ouXLrVlj<q>UKC9D/;cqBGn<!DCl?rrJR?pAY0P48]$YfgPf=!@cOtrrIA?rr3&og["k="?7J0
-,`Vg'!$2%<&RW6Okq)#ts&R/=+9/3^s%^l:rrkjCs8TB>qu6\sF6ii,OGs/<!Q&%=rrCsOrrTH1
-mf*4d*U`q.?,-(4%YoShgX7PNs6XR>s6`D>rr3!]iVic_DQj'\s1Me>A[h[="LVqC?,6I>"KZSB
-<65(=!V5UMrrLA?qu6]9=+UC&s/H$K~>
-!ouXLrVlj<q>UKC9D/;cqBGn<!DCl?rrJR?pAY0P48]$YfgPf=!@cOtrrIA?rr3&og["k="?7J0
-,`Vg'!$2%<&RW6Okq)#ts&R/=+9/3^s%^l:rrkjCs8TB>qu6\sF6ii,OGs/<!Q&%=rrCsOrrTH1
-mf*4d*U`q.?,-(4%YoShgX7PNs6XR>s6`D>rr3!]iVic_DQj'\s1Me>A[h[="LVqC?,6I>"KZSB
-<65(=!V5UMrrLA?qu6]9=+UC&s/H$K~>
-!ouXLrVlj<qYpWR7/HTV!W"#=rrGd@rr3"fK(f3FiB-r:!SKm>rrFS?rr3"DV"jrmpsqY'qu6Tq
-*W?!@?bQL(1]IC^qYgC8s/(#?:<rj^r>YtHfDklVCA\#3WcRM+!K`9=rrN(ur>Ygmq#:B"C]485
-*U`q.?,-(4"c&BCs7@c>rrd5Er7aR:rrG7@rVm1AYQ#XC]jLeN\,QC1[:oSG_#F?=XDn4+7iWLI
-oD\j9:](.m`E.WjJcD_LJ,~>
-!ouXLrVlj<qYpWR7/HTV!W"#=rrGd@rr3"fK(f3FiB-r:!SKm>rrFS?rr3"DV"jrmpsqY'qu6Tq
-*W?!@?bQL(1]IC^qYgC8s/(#?:<rj^r>YtHfDklVCA\#3WcRM+!K`9=rrN(ur>Ygmq#:B"C]485
-*U`q.?,-(4"c&BCs7@c>rrd5Er7aR:rrG7@rVm1AYQ#XC]jLeN\,QC1[:oSG_#F?=XDn4+7iWLI
-oD\j9:](.m`E.WjJcD_LJ,~>
-!ouXLrVlj<qYpWR7/HTV!W"#=rrGd@rr3"fK(f3FiB-r:!SKm>rrFS?rr3"DV"jrmpsqY'qu6Tq
-*W?!@?bQL(1]IC^qYgC8s/(#?:<rj^r>YtHfDklVCA\#3WcRM+!K`9=rrN(ur>Ygmq#:B"C]485
-*U`q.?,-(4"c&BCs7@c>rrd5Er7aR:rrG7@rVm1AYQ#XC]jLeN\,QC1[:oSG_#F?=XDn4+7iWLI
-oD\j9:](.m`E.WjJcD_LJ,~>
-!ouXLrVlj<qu6]J7e?W\qBGn<!DCl?rrJR?pAY0P48]$YfgPf=!@c+hrrIA?rr3&lcfG')!Sfs<
-rr=)<rrc]Bs62?;rsAZHs/(#?:<rM[rr3Mf37n31Z>0F>gA1dK\p3N,rs+XEs8UUKoAKTI!$1k7
-!O6G=rr=)4rrV!%r;HWr?,-(4"c&BCs7@c=rrPU@*W5pJ4Q6.is8Qu?ruM-Q?iO]Hrr3,/B`DAR
-rr3,&E;rnYrr3#ejn8WSbtn9;!rAp@r;Qincf'HTJcE"TJ,~>
-!ouXLrVlj<qu6]J7e?W\qBGn<!DCl?rrJR?pAY0P48]$YfgPf=!@c+hrrIA?rr3&lcfG')!Sfs<
-rr=)<rrc]Bs62?;rsAZHs/(#?:<rM[rr3Mf37n31Z>0F>gA1dK\p3N,rs+XEs8UUKoAKTI!$1k7
-!O6G=rr=)4rrV!%r;HWr?,-(4"c&BCs7@c=rrPU@*W5pJ4Q6.is8Qu?ruM-Q?iO]Hrr3,/B`DAR
-rr3,&E;rnYrr3#ejn8WSbtn9;!rAp@r;Qincf'HTJcE"TJ,~>
-!ouXLrVlj<qu6]J7e?W\qBGn<!DCl?rrJR?pAY0P48]$YfgPf=!@c+hrrIA?rr3&lcfG')!Sfs<
-rr=)<rrc]Bs62?;rsAZHs/(#?:<rM[rr3Mf37n31Z>0F>gA1dK\p3N,rs+XEs8UUKoAKTI!$1k7
-!O6G=rr=)4rrV!%r;HWr?,-(4"c&BCs7@c=rrPU@*W5pJ4Q6.is8Qu?ruM-Q?iO]Hrr3,/B`DAR
-rr3,&E;rnYrr3#ejn8WSbtn9;!rAp@r;Qincf'HTJcE"TJ,~>
-&*-#Ys3n9Z'XG$js8U/Gp@S@j_ljo_cN!oqT`24tMQ$:L"M:6SZI]$T#e?<UZIo3W.8^#L!I_`^
-rrU7AErH"=gd(f;!+#Q/"EMoikqi8;$2u%H_4Ua&cM1ZDZ3k[gfDklmGI"Mcl2L\`N0*E+#I/ug
-Z<@4XE;d'B>PS4!Z"s=<!$1b4!_EC^rVln(^\.U1X,+'eY%dk7!dpbLr;R:NVPeS:s-]%U'XF*e
-s-&cJZN$0ks,EHGZ36;Zs+m3EZ2ouZp&>';:]14ni]?u:!nmW^JcC<$Z2]=~>
-&*-#Ys3n9Z'XG$js8U/Gp@S@j_ljo_cN!oqT`24tMQ$:L"M:6SZI]$T#e?<UZIo3W.8^#L!I_`^
-rrU7AErH"=gd(f;!+#Q/"EMoikqi8;$2u%H_4Ua&cM1ZDZ3k[gfDklmGI"Mcl2L\`N0*E+#I/ug
-Z<@4XE;d'B>PS4!Z"s=<!$1b4!_EC^rVln(^\.U1X,+'eY%dk7!dpbLr;R:NVPeS:s-]%U'XF*e
-s-&cJZN$0ks,EHGZ36;Zs+m3EZ2ouZp&>';:]14ni]?u:!nmW^JcC<$Z2]=~>
-&*-#Ys3n9Z'XG$js8U/Gp@S@j_ljo_cN!oqT`24tMQ$:L"M:6SZI]$T#e?<UZIo3W.8^#L!I_`^
-rrU7AErH"=gd(f;!+#Q/"EMoikqi8;$2u%H_4Ua&cM1ZDZ3k[gfDklmGI"Mcl2L\`N0*E+#I/ug
-Z<@4XE;d'B>PS4!Z"s=<!$1b4!_EC^rVln(^\.U1X,+'eY%dk7!dpbLr;R:NVPeS:s-]%U'XF*e
-s-&cJZN$0ks,EHGZ36;Zs+m3EZ2ouZp&>';:]14ni]?u:!nmW^JcC<$Z2]=~>
-"QVjNs/Gp1"JPkqP32B9!/UVg!2'8j!/(8b!i5k1qj%?1s8RBDB`P=8rr@0?B`tdBs+0V;B`P[A
-rrV%kXSr/"l]1oC!;HG+"NUQBnq[/C!WIHErr\VIs60Gr!l^>crr3)9Bkc?#rrTfah<b.GXD)D;
-s8U7?B`Rf#rrLNGrVlkDp&>)W'(Pr#"'oo4T_ABfVeKj`qu6\Hq>:0mH?oJh"INm3Boi8n!0dCr
-!0mK_!07%m!1Eid!/^\h!1roa"/_B0:]14nOc0,:!pOEmJcC<$Z2]=~>
-"QVjNs/Gp1"JPkqP32B9!/UVg!2'8j!/(8b!i5k1qj%?1s8RBDB`P=8rr@0?B`tdBs+0V;B`P[A
-rrV%kXSr/"l]1oC!;HG+"NUQBnq[/C!WIHErr\VIs60Gr!l^>crr3)9Bkc?#rrTfah<b.GXD)D;
-s8U7?B`Rf#rrLNGrVlkDp&>)W'(Pr#"'oo4T_ABfVeKj`qu6\Hq>:0mH?oJh"INm3Boi8n!0dCr
-!0mK_!07%m!1Eid!/^\h!1roa"/_B0:]14nOc0,:!pOEmJcC<$Z2]=~>
-"QVjNs/Gp1"JPkqP32B9!/UVg!2'8j!/(8b!i5k1qj%?1s8RBDB`P=8rr@0?B`tdBs+0V;B`P[A
-rrV%kXSr/"l]1oC!;HG+"NUQBnq[/C!WIHErr\VIs60Gr!l^>crr3)9Bkc?#rrTfah<b.GXD)D;
-s8U7?B`Rf#rrLNGrVlkDp&>)W'(Pr#"'oo4T_ABfVeKj`qu6\Hq>:0mH?oJh"INm3Boi8n!0dCr
-!0mK_!07%m!1Eid!/^\h!1roa"/_B0:]14nOc0,:!pOEmJcC<$Z2]=~>
-!ouXLg&D&Xqh5$jXoAF5fYd^i/+NT<"0mQ6OPKj9*SgYsQ\C-or;Qb\JcC<$VuM8~>
-!ouXLg&D&Xqh5$jXoAF5fYd^i/+NT<"0mQ6OPKj9*SgYsQ\C-or;Qb\JcC<$VuM8~>
-!ouXLg&D&Xqh5$jXoAF5fYd^i/+NT<"0mQ6OPKj9*SgYsQ\C-or;Qb\JcC<$VuM8~>
-!ouXLJcEIa!fWE@eGfLhJcC<$JcGNFJ,~>
-!ouXLJcEIa!fWE@eGfLhJcC<$JcGNFJ,~>
-!ouXLJcEIa!fWE@eGfLhJcC<$JcGNFJ,~>
-!ouXLJcEIa!RUJfrrBugs+13$s7lVE~>
-!ouXLJcEIa!RUJfrrBugs+13$s7lVE~>
-!ouXLJcEIa!RUJfrrBugs+13$s7lVE~>
-!ouXLrr3't-73*urrYk?->%i/VuHj>-71q,rrYb<->A&2JcDGDJ,~>
-!ouXLrr3't-73*urrYk?->%i/VuHj>-71q,rrYb<->A&2JcDGDJ,~>
-!ouXLrr3't-73*urrYk?->%i/VuHj>-71q,rrYb<->A&2JcDGDJ,~>
-!ouXLrr3'UiUusDrs(%<p%\ReoM>H+"C_!'=r@2X",R!J62hi)Dt`u+!V%uF*!C]as#M+t*!3#;
-5lDZ''<(^+!:'M&".8rb)Z1QV`W%.\*!$Vlq>UKpc2AUb[/Bt%Y5TCHaoDD<V]6\VqtU0lr3?2?
-"47(m&H*RN*rl,4r>Ygpq#:BkQMhd'mem(cnKn27"SQdS*96en!V^p>*!%tfr;Qr]1&q:ID#PCZ
-7.^HYq"=;#o`#1Qo$gS;s)5IHo)Ae=s1<%Frr_uf`D;'bJcDGDJ,~>
-!ouXLrr3'UiUusDrs(%<p%\ReoM>H+"C_!'=r@2X",R!J62hi)Dt`u+!V%uF*!C]as#M+t*!3#;
-5lDZ''<(^+!:'M&".8rb)Z1QV`W%.\*!$Vlq>UKpc2AUb[/Bt%Y5TCHaoDD<V]6\VqtU0lr3?2?
-"47(m&H*RN*rl,4r>Ygpq#:BkQMhd'mem(cnKn27"SQdS*96en!V^p>*!%tfr;Qr]1&q:ID#PCZ
-7.^HYq"=;#o`#1Qo$gS;s)5IHo)Ae=s1<%Frr_uf`D;'bJcDGDJ,~>
-!ouXLrr3'UiUusDrs(%<p%\ReoM>H+"C_!'=r@2X",R!J62hi)Dt`u+!V%uF*!C]as#M+t*!3#;
-5lDZ''<(^+!:'M&".8rb)Z1QV`W%.\*!$Vlq>UKpc2AUb[/Bt%Y5TCHaoDD<V]6\VqtU0lr3?2?
-"47(m&H*RN*rl,4r>Ygpq#:BkQMhd'mem(cnKn27"SQdS*96en!V^p>*!%tfr;Qr]1&q:ID#PCZ
-7.^HYq"=;#o`#1Qo$gS;s)5IHo)Ae=s1<%Frr_uf`D;'bJcDGDJ,~>
-!ouXLrr3!SlMLS^.eEW=!F3J?rrfBBs&7&:rrGd@rr3"fK)#?H3o^/="Gr?B1$eT6!pk9@q#:=7
-rVlt4[Jq9@rrV=od/!\BodB_<"@^r?ZYfX?#PtQEs8R)Bqt^6mdn0N<"!m]c;>^@o_HQp<!$1k7
-!O6G=rr=)<rsRa\$ig7pJueqO6eV87!K`<?rrM"?rVm)U2_"e,J"HZ>!R=I<rr=)3rrXeBdRsN=
-!C,E2rrX;A\7GO;!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eEW=!F3J?rrfBBs&7&:rrGd@rr3"fK)#?H3o^/="Gr?B1$eT6!pk9@q#:=7
-rVlt4[Jq9@rrV=od/!\BodB_<"@^r?ZYfX?#PtQEs8R)Bqt^6mdn0N<"!m]c;>^@o_HQp<!$1k7
-!O6G=rr=)<rsRa\$ig7pJueqO6eV87!K`<?rrM"?rVm)U2_"e,J"HZ>!R=I<rr=)3rrXeBdRsN=
-!C,E2rrX;A\7GO;!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eEW=!F3J?rrfBBs&7&:rrGd@rr3"fK)#?H3o^/="Gr?B1$eT6!pk9@q#:=7
-rVlt4[Jq9@rrV=od/!\BodB_<"@^r?ZYfX?#PtQEs8R)Bqt^6mdn0N<"!m]c;>^@o_HQp<!$1k7
-!O6G=rr=)<rsRa\$ig7pJueqO6eV87!K`<?rrM"?rVm)U2_"e,J"HZ>!R=I<rr=)3rrXeBdRsN=
-!C,E2rrX;A\7GO;!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eEW=!F3J?rt2;Os&7%P[C+B]s*rr+s6>N>q#:@Uir8r\M3Irokl.sigACmN
-QA>57!$2%<"D>.B*V99<!9="W!oJ@Aq#:Bf-iO&I7G$o\qu6of@a>#Rc!]u8rrLS?rVm!Gq9)Xm
-rj;k&s2%t<rr=)7rrKB?rVlj<rr3DWCt]p0s1Eg>s8TE?q#:AVNW/qYh`^u=#KpH:.KBEtT)S`j
-c;+<;!$1_3").AbJ,]HLGGkH=rrp[9]sY8prVlt,s36](rrLA?JcC<$U&TW~>
-!ouXLrr3!SlMLS^.eEW=!F3J?rt2;Os&7%P[C+B]s*rr+s6>N>q#:@Uir8r\M3Irokl.sigACmN
-QA>57!$2%<"D>.B*V99<!9="W!oJ@Aq#:Bf-iO&I7G$o\qu6of@a>#Rc!]u8rrLS?rVm!Gq9)Xm
-rj;k&s2%t<rr=)7rrKB?rVlj<rr3DWCt]p0s1Eg>s8TE?q#:AVNW/qYh`^u=#KpH:.KBEtT)S`j
-c;+<;!$1_3").AbJ,]HLGGkH=rrp[9]sY8prVlt,s36](rrLA?JcC<$U&TW~>
-!ouXLrr3!SlMLS^.eEW=!F3J?rt2;Os&7%P[C+B]s*rr+s6>N>q#:@Uir8r\M3Irokl.sigACmN
-QA>57!$2%<"D>.B*V99<!9="W!oJ@Aq#:Bf-iO&I7G$o\qu6of@a>#Rc!]u8rrLS?rVm!Gq9)Xm
-rj;k&s2%t<rr=)7rrKB?rVlj<rr3DWCt]p0s1Eg>s8TE?q#:AVNW/qYh`^u=#KpH:.KBEtT)S`j
-c;+<;!$1_3").AbJ,]HLGGkH=rrp[9]sY8prVlt,s36](rrLA?JcC<$U&TW~>
-!ouXLrr3!SlMLS^.eEW=%U?jMs6409s&42YAnH;1rVlreMkg%H#s.)Gs4gM9s"TH2Ac[D5rVlrX
-KX^^U!$2(="jT<>rtpjsAc[YJrr3)X=&duMrrMd?rr3/<.bF&Ai;T,MkPtS<GF=kBht[3Pdn0Q=
-"g\s>b;"YKAcn:t_HQs=!N[(3rrKB?rr38#*WQ/eI*Va4rr3,/Kpe?Lp\u"jNW9%XL->S:_fb#3
-.KBEtT)\ibHqsV>!$1G+!ILR>rruGICM%1'an>Z7btiojJcDGDJ,~>
-!ouXLrr3!SlMLS^.eEW=%U?jMs6409s&42YAnH;1rVlreMkg%H#s.)Gs4gM9s"TH2Ac[D5rVlrX
-KX^^U!$2(="jT<>rtpjsAc[YJrr3)X=&duMrrMd?rr3/<.bF&Ai;T,MkPtS<GF=kBht[3Pdn0Q=
-"g\s>b;"YKAcn:t_HQs=!N[(3rrKB?rr38#*WQ/eI*Va4rr3,/Kpe?Lp\u"jNW9%XL->S:_fb#3
-.KBEtT)\ibHqsV>!$1G+!ILR>rruGICM%1'an>Z7btiojJcDGDJ,~>
-!ouXLrr3!SlMLS^.eEW=%U?jMs6409s&42YAnH;1rVlreMkg%H#s.)Gs4gM9s"TH2Ac[D5rVlrX
-KX^^U!$2(="jT<>rtpjsAc[YJrr3)X=&duMrrMd?rr3/<.bF&Ai;T,MkPtS<GF=kBht[3Pdn0Q=
-"g\s>b;"YKAcn:t_HQs=!N[(3rrKB?rr38#*WQ/eI*Va4rr3,/Kpe?Lp\u"jNW9%XL->S:_fb#3
-.KBEtT)\ibHqsV>!$1G+!ILR>rruGICM%1'an>Z7btiojJcDGDJ,~>
-!ouXLrr3!SlMLS^.eEW=%^1>0I=>7;s/UbCs8Sj?rr3&pI\lc<$(cToI=F_Ms-e`BrrI\@rVlo)
-C%hQ,NrFG1Il4Y6MO4>B!FNP>rrgr*Jq)eUrrMtIrd=s#,M2<!If=p)Idd<rItE9%jS8`Ul@Jq_
-"b@<^jat#ArrX;AiILoU!J(s[rrLf'rd>''*<4K;aoDA]rr3,:J:`B,p\t98J,Xj)E]sH>JD'tp
-.KBF`J,XisBhnU+!$1D*!$2%<##o4*s8Sm?p&>';:P&Oss.TIC~>
-!ouXLrr3!SlMLS^.eEW=%^1>0I=>7;s/UbCs8Sj?rr3&pI\lc<$(cToI=F_Ms-e`BrrI\@rVlo)
-C%hQ,NrFG1Il4Y6MO4>B!FNP>rrgr*Jq)eUrrMtIrd=s#,M2<!If=p)Idd<rItE9%jS8`Ul@Jq_
-"b@<^jat#ArrX;AiILoU!J(s[rrLf'rd>''*<4K;aoDA]rr3,:J:`B,p\t98J,Xj)E]sH>JD'tp
-.KBF`J,XisBhnU+!$1D*!$2%<##o4*s8Sm?p&>';:P&Oss.TIC~>
-!ouXLrr3!SlMLS^.eEW=%^1>0I=>7;s/UbCs8Sj?rr3&pI\lc<$(cToI=F_Ms-e`BrrI\@rVlo)
-C%hQ,NrFG1Il4Y6MO4>B!FNP>rrgr*Jq)eUrrMtIrd=s#,M2<!If=p)Idd<rItE9%jS8`Ul@Jq_
-"b@<^jat#ArrX;AiILoU!J(s[rrLf'rd>''*<4K;aoDA]rr3,:J:`B,p\t98J,Xj)E]sH>JD'tp
-.KBF`J,XisBhnU+!$1D*!$2%<##o4*s8Sm?p&>';:P&Oss.TIC~>
-!ouXLrr3!SlMLS^.eET<"h("oZ`A*CrrJm@rr3":Y4V_tWLf]sM3Ii:!J-d?rrV2$`qKE4rViAi
-c"FH]rrHK?qu6[t`q]Q6nG]!_fgXN[*kVFO#sI26DSQ5O]l*B8rrD*YSc\%"q>:0o*WQ/qrgj/X
-*V]R6f)D6Do,[k1/H0&a$[;WhJ(Xf$TR?M6(!<,>TAMg3LH/dO>n;nos21G"VTqs7rr=)*rrJR?
-rr3!uaSu2?Uj;Y5!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eET<"h("oZ`A*CrrJm@rr3":Y4V_tWLf]sM3Ii:!J-d?rrV2$`qKE4rViAi
-c"FH]rrHK?qu6[t`q]Q6nG]!_fgXN[*kVFO#sI26DSQ5O]l*B8rrD*YSc\%"q>:0o*WQ/qrgj/X
-*V]R6f)D6Do,[k1/H0&a$[;WhJ(Xf$TR?M6(!<,>TAMg3LH/dO>n;nos21G"VTqs7rr=)*rrJR?
-rr3!uaSu2?Uj;Y5!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eET<"h("oZ`A*CrrJm@rr3":Y4V_tWLf]sM3Ii:!J-d?rrV2$`qKE4rViAi
-c"FH]rrHK?qu6[t`q]Q6nG]!_fgXN[*kVFO#sI26DSQ5O]l*B8rrD*YSc\%"q>:0o*WQ/qrgj/X
-*V]R6f)D6Do,[k1/H0&a$[;WhJ(Xf$TR?M6(!<,>TAMg3LH/dO>n;nos21G"VTqs7rr=)*rrJR?
-rr3!uaSu2?Uj;Y5!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eEH8!NU5;rro0Ds8Q]>n,EEFPPb@\JXl`>!ROO0rrHc?qu6\(^&.g1<lXb2
-"%Ci/0`D"R4l><[rVlmUkk"fT,l.?;!$1q9!$1Y1!Zh=)rON+H`;cKXrr3#g/G&lDh`_"srji0:
-*mOT^!R=I<rr=)*rs&7lJcGaLaSu2?Uj;Y5!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eEH8!NU5;rro0Ds8Q]>n,EEFPPb@\JXl`>!ROO0rrHc?qu6\(^&.g1<lXb2
-"%Ci/0`D"R4l><[rVlmUkk"fT,l.?;!$1q9!$1Y1!Zh=)rON+H`;cKXrr3#g/G&lDh`_"srji0:
-*mOT^!R=I<rr=)*rs&7lJcGaLaSu2?Uj;Y5!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eEH8!NU5;rro0Ds8Q]>n,EEFPPb@\JXl`>!ROO0rrHc?qu6\(^&.g1<lXb2
-"%Ci/0`D"R4l><[rVlmUkk"fT,l.?;!$1q9!$1Y1!Zh=)rON+H`;cKXrr3#g/G&lDh`_"srji0:
-*mOT^!R=I<rr=)*rs&7lJcGaLaSu2?Uj;Y5!R4Dks+13Ds*t~>
-!ouXLrr3!SlMLS^.eEK9"jpfCs)6?brro0Ds(Jn>qYpWa.;\k\"grXDs&/:ars"%Es8VR[iqr`W
-cmaeIrre^NoD_,TrrZWAs$?V`!ER5>rrTPVV>C2pI&Hf-0`D"X4l?.@E<#rUZMXY$!gkFQqYp\*
-^AcSurVlj<qu6[obPhGBHR[hJrrGL?qu6sCs8VS?WW2u_h>R?T?RbjKrrW-`i;ETUoI9\;!q&\@
-r;Qa;qu6[Y8Flcaa]&6><65(=!Mk#6rrLA?JcC<$U&TW~>
-!ouXLrr3!SlMLS^.eEK9"jpfCs)6?brro0Ds(Jn>qYpWa.;\k\"grXDs&/:ars"%Es8VR[iqr`W
-cmaeIrre^NoD_,TrrZWAs$?V`!ER5>rrTPVV>C2pI&Hf-0`D"X4l?.@E<#rUZMXY$!gkFQqYp\*
-^AcSurVlj<qu6[obPhGBHR[hJrrGL?qu6sCs8VS?WW2u_h>R?T?RbjKrrW-`i;ETUoI9\;!q&\@
-r;Qa;qu6[Y8Flcaa]&6><65(=!Mk#6rrLA?JcC<$U&TW~>
-!ouXLrr3!SlMLS^.eEK9"jpfCs)6?brro0Ds(Jn>qYpWa.;\k\"grXDs&/:ars"%Es8VR[iqr`W
-cmaeIrre^NoD_,TrrZWAs$?V`!ER5>rrTPVV>C2pI&Hf-0`D"X4l?.@E<#rUZMXY$!gkFQqYp\*
-^AcSurVlj<qu6[obPhGBHR[hJrrGL?qu6sCs8VS?WW2u_h>R?T?RbjKrrW-`i;ETUoI9\;!q&\@
-r;Qa;qu6[Y8Flcaa]&6><65(=!Mk#6rrLA?JcC<$U&TW~>
-!ouXLrr3'Uh!jt7rrXb3nFZ_[#ZMc`9(r;bp.>6'"D[`3<Z:oV!0I3[!p^7krVm-\*#rScs8VaD
-rYu)rqZ$T`48SsYb6i:hrrDop*!Cojs8V9\*!;u6s5<hq!NQ(srrT5,PlC[_h#88rTD\`gb5E:c
-^]"31WuN+^r;HWsM[$WhrrBe4*!EqQs89%u*!>!rs0)DA!QtE?rrQs=fDbdMT`,o2f_YUJ/,oPO
-q/RGpkPY>]9EP%hrrdon*$4bLrrMaLrr3+B*#pR'rr3)nnF.IqrrF>jo)AmkXapFYbPqMBWIagD
-"7krt:P&Oss.TIC~>
-!ouXLrr3'Uh!jt7rrXb3nFZ_[#ZMc`9(r;bp.>6'"D[`3<Z:oV!0I3[!p^7krVm-\*#rScs8VaD
-rYu)rqZ$T`48SsYb6i:hrrDop*!Cojs8V9\*!;u6s5<hq!NQ(srrT5,PlC[_h#88rTD\`gb5E:c
-^]"31WuN+^r;HWsM[$WhrrBe4*!EqQs89%u*!>!rs0)DA!QtE?rrQs=fDbdMT`,o2f_YUJ/,oPO
-q/RGpkPY>]9EP%hrrdon*$4bLrrMaLrr3+B*#pR'rr3)nnF.IqrrF>jo)AmkXapFYbPqMBWIagD
-"7krt:P&Oss.TIC~>
-!ouXLrr3'Uh!jt7rrXb3nFZ_[#ZMc`9(r;bp.>6'"D[`3<Z:oV!0I3[!p^7krVm-\*#rScs8VaD
-rYu)rqZ$T`48SsYb6i:hrrDop*!Cojs8V9\*!;u6s5<hq!NQ(srrT5,PlC[_h#88rTD\`gb5E:c
-^]"31WuN+^r;HWsM[$WhrrBe4*!EqQs89%u*!>!rs0)DA!QtE?rrQs=fDbdMT`,o2f_YUJ/,oPO
-q/RGpkPY>]9EP%hrrdon*$4bLrrMaLrr3+B*#pR'rr3)nnF.IqrrF>jo)AmkXapFYbPqMBWIagD
-"7krt:P&Oss.TIC~>
-!ouXLrr3(#.k>-.rrZ"H.r+/F!R+C#rrK-?j8T.9PiMcEB=?k#!CbW#rrFA?k5PO+.k=!arrMm@
-h>[RM.k>Ifs+13Ds*t~>
-!ouXLrr3(#.k>-.rrZ"H.r+/F!R+C#rrK-?j8T.9PiMcEB=?k#!CbW#rrFA?k5PO+.k=!arrMm@
-h>[RM.k>Ifs+13Ds*t~>
-!ouXLrr3(#.k>-.rrZ"H.r+/F!R+C#rrK-?j8T.9PiMcEB=?k#!CbW#rrFA?k5PO+.k=!arrMm@
-h>[RM.k>Ifs+13Ds*t~>
-!ouXLf)GgITn2;)!q2;?jSo;DK<jS<!o8"AjSo;1B&htP!m4UAh#@Dd@Y+Q1s+14Gs*t~>
-!ouXLf)GgITn2;)!q2;?jSo;DK<jS<!o8"AjSo;1B&htP!m4UAh#@Dd@Y+Q1s+14Gs*t~>
-!ouXLf)GgITn2;)!q2;?jSo;DK<jS<!o8"AjSo;1B&htP!m4UAh#@Dd@Y+Q1s+14Gs*t~>
-!ouXLf)GdAK&ck3h3[1%!QhG'rrKLBj8T.Pe`6Z1MsB's!-NkmJcC<$q#>j~>
-!ouXLf)GdAK&ck3h3[1%!QhG'rrKLBj8T.Pe`6Z1MsB's!-NkmJcC<$q#>j~>
-!ouXLf)GdAK&ck3h3[1%!QhG'rrKLBj8T.Pe`6Z1MsB's!-NkmJcC<$q#>j~>
-!ouXLL&V1cdZa\2NkPGmp\oXB_RKOFg\u[&hYmHTaMn&V!Q<*2s-Nb9~>
-!ouXLL&V1cdZa\2NkPGmp\oXB_RKOFg\u[&hYmHTaMn&V!Q<*2s-Nb9~>
-!ouXLL&V1cdZa\2NkPGmp\oXB_RKOFg\u[&hYmHTaMn&V!Q<*2s-Nb9~>
-"lqsOs8S>_@fVJerrJ2Co)A`3GfB[_Fl<9$^4G)<rrUAR]C#V#c!t8,r;Qi,A'k5T!S*h3rrSHq
-B[m%_G,G3;",$1/N;ih\O(7qad\H:2"b:Cgs2))8rr[EDb,b79"R[8"SC%98#OmHI]"7qAr;L1+
-Xks'Xj8EHfg%PFR`if?(j8]/>S=DXRrVlrKIEMKf!muA@JcD,;J,~>
-"lqsOs8S>_@fVJerrJ2Co)A`3GfB[_Fl<9$^4G)<rrUAR]C#V#c!t8,r;Qi,A'k5T!S*h3rrSHq
-B[m%_G,G3;",$1/N;ih\O(7qad\H:2"b:Cgs2))8rr[EDb,b79"R[8"SC%98#OmHI]"7qAr;L1+
-Xks'Xj8EHfg%PFR`if?(j8]/>S=DXRrVlrKIEMKf!muA@JcD,;J,~>
-"lqsOs8S>_@fVJerrJ2Co)A`3GfB[_Fl<9$^4G)<rrUAR]C#V#c!t8,r;Qi,A'k5T!S*h3rrSHq
-B[m%_G,G3;",$1/N;ih\O(7qad\H:2"b:Cgs2))8rr[EDb,b79"R[8"SC%98#OmHI]"7qAr;L1+
-Xks'Xj8EHfg%PFR`if?(j8]/>S=DXRrVlrKIEMKf!muA@JcD,;J,~>
-"lqsOs-ArL\-AC]s8U8Gp@J:b^VS_*!V0skrr=(trrJC?r;Qi]\DZcS"6d6nWVlbthRMhLrrK]?
-nc&`YPdn,0hZ!V$j8/cV*rc*;$o@/%6N@(IR(-<![:oR>!FYftrs!qIZ=X'*JbK*G*WN'\pAY0]
-0)PYRju37"NrT,`rjVu\[,Crbo3D7(!Ft<errf'Bs%:`;rrHK?r;Qe>W;HSqCpAQkR/_[~>
-"lqsOs-ArL\-AC]s8U8Gp@J:b^VS_*!V0skrr=(trrJC?r;Qi]\DZcS"6d6nWVlbthRMhLrrK]?
-nc&`YPdn,0hZ!V$j8/cV*rc*;$o@/%6N@(IR(-<![:oR>!FYftrs!qIZ=X'*JbK*G*WN'\pAY0]
-0)PYRju37"NrT,`rjVu\[,Crbo3D7(!Ft<errf'Bs%:`;rrHK?r;Qe>W;HSqCpAQkR/_[~>
-"lqsOs-ArL\-AC]s8U8Gp@J:b^VS_*!V0skrr=(trrJC?r;Qi]\DZcS"6d6nWVlbthRMhLrrK]?
-nc&`YPdn,0hZ!V$j8/cV*rc*;$o@/%6N@(IR(-<![:oR>!FYftrs!qIZ=X'*JbK*G*WN'\pAY0]
-0)PYRju37"NrT,`rjVu\[,Crbo3D7(!Ft<errf'Bs%:`;rrHK?r;Qe>W;HSqCpAQkR/_[~>
-"lqsOs)#">rrKc?rr3#R6HoH1m4[i+!$1%u!l&a@j8T.$WV6>m\mk40"E(CBpa"_r!CYT;rrHE@
-qu7'\l.SK(s(/\>b:?iZrr3!CqXsjm9[NaJ.rFSFrrX;AW-.h6!U_T;rs.[Es,N->ruM+=!JZs!
-rrW,+CB"56hYHpG"JU5B9%*Y;!FNP<rrV@pci!eEk$Q\js-`n;~>
-"lqsOs)#">rrKc?rr3#R6HoH1m4[i+!$1%u!l&a@j8T.$WV6>m\mk40"E(CBpa"_r!CYT;rrHE@
-qu7'\l.SK(s(/\>b:?iZrr3!CqXsjm9[NaJ.rFSFrrX;AW-.h6!U_T;rs.[Es,N->ruM+=!JZs!
-rrW,+CB"56hYHpG"JU5B9%*Y;!FNP<rrV@pci!eEk$Q\js-`n;~>
-"lqsOs)#">rrKc?rr3#R6HoH1m4[i+!$1%u!l&a@j8T.$WV6>m\mk40"E(CBpa"_r!CYT;rrHE@
-qu7'\l.SK(s(/\>b:?iZrr3!CqXsjm9[NaJ.rFSFrrX;AW-.h6!U_T;rs.[Es,N->ruM+=!JZs!
-rrW,+CB"56hYHpG"JU5B9%*Y;!FNP<rrV@pci!eEk$Q\js-`n;~>
-$KOKTs7Z<hs3js?rVlrY6h^6R!_aRerVlol6N.r*EV]V6!p^A$rr3!gf_uj%J,91/m/R*]LB%9=
-)?h*#PkY1Xn,44/S,<4+cMedcU\t/Xr>Z3Fr;JVFV]6\]rVt:D*!NkNs8TB>r;QlD*#=n?rrN)2
-r>Yj_rq??mF/f-<"0W[Z[f6:.\m:*j*!#='rrQ^Air/l^DQa$>o)JQDrYuV$o`(\EnkpG]p&C<n
-*5aNjp&G&<rYu2-pA^*l#8eFOrVlm\iVWWkoD\^\s8Vfis8MN[s8R!W"<8Cns8VdbrYuMaq#C!a
-s8DH\s8PmA,9.\Iq>UBrnc/I[pAY0]0)PYRrU^'aq#C@7rpg2AQiI(9rVm%8_#OG]>5\C+/,u]"
-s'!eLdet-g\,H<I&cNaP^A\&Lr>Z*^rr<#op]'m`r;Qe)^&.g1=2t.;!D^pks-`n;~>
-$KOKTs7Z<hs3js?rVlrY6h^6R!_aRerVlol6N.r*EV]V6!p^A$rr3!gf_uj%J,91/m/R*]LB%9=
-)?h*#PkY1Xn,44/S,<4+cMedcU\t/Xr>Z3Fr;JVFV]6\]rVt:D*!NkNs8TB>r;QlD*#=n?rrN)2
-r>Yj_rq??mF/f-<"0W[Z[f6:.\m:*j*!#='rrQ^Air/l^DQa$>o)JQDrYuV$o`(\EnkpG]p&C<n
-*5aNjp&G&<rYu2-pA^*l#8eFOrVlm\iVWWkoD\^\s8Vfis8MN[s8R!W"<8Cns8VdbrYuMaq#C!a
-s8DH\s8PmA,9.\Iq>UBrnc/I[pAY0]0)PYRrU^'aq#C@7rpg2AQiI(9rVm%8_#OG]>5\C+/,u]"
-s'!eLdet-g\,H<I&cNaP^A\&Lr>Z*^rr<#op]'m`r;Qe)^&.g1=2t.;!D^pks-`n;~>
-$KOKTs7Z<hs3js?rVlrY6h^6R!_aRerVlol6N.r*EV]V6!p^A$rr3!gf_uj%J,91/m/R*]LB%9=
-)?h*#PkY1Xn,44/S,<4+cMedcU\t/Xr>Z3Fr;JVFV]6\]rVt:D*!NkNs8TB>r;QlD*#=n?rrN)2
-r>Yj_rq??mF/f-<"0W[Z[f6:.\m:*j*!#='rrQ^Air/l^DQa$>o)JQDrYuV$o`(\EnkpG]p&C<n
-*5aNjp&G&<rYu2-pA^*l#8eFOrVlm\iVWWkoD\^\s8Vfis8MN[s8R!W"<8Cns8VdbrYuMaq#C!a
-s8DH\s8PmA,9.\Iq>UBrnc/I[pAY0]0)PYRrU^'aq#C@7rpg2AQiI(9rVm%8_#OG]>5\C+/,u]"
-s'!eLdet-g\,H<I&cNaP^A\&Lr>Z*^rr<#op]'m`r;Qe)^&.g1=2t.;!D^pks-`n;~>
-!ouXLrVloJ8c&Gfd7a04!W"#=rrGd@rr3"fK)YcOm3ulNrrG/,rr37\PQ*B's8S[>rr3#d0D,8E
-*W?!@JAM6u:&b.n?bQ@:$Wb:Ii!OT+s%^l4-iO&KA)71bZ>079!K<->rrLn@rVlmLnFlk_F/f':
-!Gf"?rrTbCPlC[_*W?!JF=H>Os7+ZGP1KO1s.Fc=rt4`Os8REaaoCN]s,`6?39B$\qu6]J7fNDg
-7+hD:!Bf?,rrF>?rVlmtaSu2?ZB"_[#"'X1s8S:?n,EFV0(f/D)ZD/q'pnt#5McA>l>"B>s34C<
-rs0\GVfi#8c1WL_rrYdBmP"P="$YT'2uWaW<pTGY!FNP;rrH3@qu6[lc@Q"`s*t~>
-!ouXLrVloJ8c&Gfd7a04!W"#=rrGd@rr3"fK)YcOm3ulNrrG/,rr37\PQ*B's8S[>rr3#d0D,8E
-*W?!@JAM6u:&b.n?bQ@:$Wb:Ii!OT+s%^l4-iO&KA)71bZ>079!K<->rrLn@rVlmLnFlk_F/f':
-!Gf"?rrTbCPlC[_*W?!JF=H>Os7+ZGP1KO1s.Fc=rt4`Os8REaaoCN]s,`6?39B$\qu6]J7fNDg
-7+hD:!Bf?,rrF>?rVlmtaSu2?ZB"_[#"'X1s8S:?n,EFV0(f/D)ZD/q'pnt#5McA>l>"B>s34C<
-rs0\GVfi#8c1WL_rrYdBmP"P="$YT'2uWaW<pTGY!FNP;rrH3@qu6[lc@Q"`s*t~>
-!ouXLrVloJ8c&Gfd7a04!W"#=rrGd@rr3"fK)YcOm3ulNrrG/,rr37\PQ*B's8S[>rr3#d0D,8E
-*W?!@JAM6u:&b.n?bQ@:$Wb:Ii!OT+s%^l4-iO&KA)71bZ>079!K<->rrLn@rVlmLnFlk_F/f':
-!Gf"?rrTbCPlC[_*W?!JF=H>Os7+ZGP1KO1s.Fc=rt4`Os8REaaoCN]s,`6?39B$\qu6]J7fNDg
-7+hD:!Bf?,rrF>?rVlmtaSu2?ZB"_[#"'X1s8S:?n,EFV0(f/D)ZD/q'pnt#5McA>l>"B>s34C<
-rs0\GVfi#8c1WL_rrYdBmP"P="$YT'2uWaW<pTGY!FNP;rrH3@qu6[lc@Q"`s*t~>
-!ouXLrr3#?<Vl^sqPAT4rrMs?rVlmkdf07IRY(>7!BT6>rs4IFs"Wj>s.4]=rrML?o`"n3qYpO9
-rVlt,^&Rp,\cb7;s56$=rr[`)pfIF*!:9^b!O?J:rrJ(?rr3#S62gfa/F`B5!HY7;rrHo@rr3#1
-@f?<,*VfX@^dT:t7IU9VTR?b='_![Rs*LL?s6a\&OH'9"jki6$s4@7]!M)^ZrrGO?qu6[ZiTpLE
-,5V9<!J7$E\cC4RrrGL?rr3"_MXUQGmOn/3!$2(=$&4fHs7.Z>s*^O=rrLA@r;R$Ds/1#>:X/S[
-rVlsif'Y3irrYIAlsB\&!9s+T!FNP;rrH3@qu6[lc@Q"`s*t~>
-!ouXLrr3#?<Vl^sqPAT4rrMs?rVlmkdf07IRY(>7!BT6>rs4IFs"Wj>s.4]=rrML?o`"n3qYpO9
-rVlt,^&Rp,\cb7;s56$=rr[`)pfIF*!:9^b!O?J:rrJ(?rr3#S62gfa/F`B5!HY7;rrHo@rr3#1
-@f?<,*VfX@^dT:t7IU9VTR?b='_![Rs*LL?s6a\&OH'9"jki6$s4@7]!M)^ZrrGO?qu6[ZiTpLE
-,5V9<!J7$E\cC4RrrGL?rr3"_MXUQGmOn/3!$2(=$&4fHs7.Z>s*^O=rrLA@r;R$Ds/1#>:X/S[
-rVlsif'Y3irrYIAlsB\&!9s+T!FNP;rrH3@qu6[lc@Q"`s*t~>
-!ouXLrr3#?<Vl^sqPAT4rrMs?rVlmkdf07IRY(>7!BT6>rs4IFs"Wj>s.4]=rrML?o`"n3qYpO9
-rVlt,^&Rp,\cb7;s56$=rr[`)pfIF*!:9^b!O?J:rrJ(?rr3#S62gfa/F`B5!HY7;rrHo@rr3#1
-@f?<,*VfX@^dT:t7IU9VTR?b='_![Rs*LL?s6a\&OH'9"jki6$s4@7]!M)^ZrrGO?qu6[ZiTpLE
-,5V9<!J7$E\cC4RrrGL?rr3"_MXUQGmOn/3!$2(=$&4fHs7.Z>s*^O=rrLA@r;R$Ds/1#>:X/S[
-rVlsif'Y3irrYIAlsB\&!9s+T!FNP;rrH3@qu6[lc@Q"`s*t~>
-#NS0Qs8T`Ko(r@eT76G4!W"#=rrGd@rr3"fK)#?H3o^/=#`4cF1$el>Spp\=!UVQ4rr=)9rr=)<
-rrZWAs-rsq"<kebi&po:!9a;h"c`$Os0?D9rrJ(?rr3#S62gfa/F`B5!HY7;rrHo@rr3#1@f?<,
-*VTL6DQ`s<!MFi>rrqmCs8RG?r;R(bNW2!"h`_"eHN%=R;+CQb!CYT;rrG7@li-u0qY^?nKDo9[
-GKfj^!CPQ>rrJ=@n,EFV0(f/D*WH'FL6qr?pM7=mJ&M?d!R4I=rs0\GVfi#8c1WL_rrYdBmP"P=
-"$YT7OoAbhbk(i8?bQ@:!E[;<rrGm?JcD/<J,~>
-#NS0Qs8T`Ko(r@eT76G4!W"#=rrGd@rr3"fK)#?H3o^/=#`4cF1$el>Spp\=!UVQ4rr=)9rr=)<
-rrZWAs-rsq"<kebi&po:!9a;h"c`$Os0?D9rrJ(?rr3#S62gfa/F`B5!HY7;rrHo@rr3#1@f?<,
-*VTL6DQ`s<!MFi>rrqmCs8RG?r;R(bNW2!"h`_"eHN%=R;+CQb!CYT;rrG7@li-u0qY^?nKDo9[
-GKfj^!CPQ>rrJ=@n,EFV0(f/D*WH'FL6qr?pM7=mJ&M?d!R4I=rs0\GVfi#8c1WL_rrYdBmP"P=
-"$YT7OoAbhbk(i8?bQ@:!E[;<rrGm?JcD/<J,~>
-#NS0Qs8T`Ko(r@eT76G4!W"#=rrGd@rr3"fK)#?H3o^/=#`4cF1$el>Spp\=!UVQ4rr=)9rr=)<
-rrZWAs-rsq"<kebi&po:!9a;h"c`$Os0?D9rrJ(?rr3#S62gfa/F`B5!HY7;rrHo@rr3#1@f?<,
-*VTL6DQ`s<!MFi>rrqmCs8RG?r;R(bNW2!"h`_"eHN%=R;+CQb!CYT;rrG7@li-u0qY^?nKDo9[
-GKfj^!CPQ>rrJ=@n,EFV0(f/D*WH'FL6qr?pM7=mJ&M?d!R4I=rs0\GVfi#8c1WL_rrYdBmP"P=
-"$YT7OoAbhbk(i8?bQ@:!E[;<rrGm?JcD/<J,~>
-#38'Ps0mL>qYpS^L@bEGqBGn<!DCl?rrJR?rr3&lJuSbL!BP?%rs4IFs"Wj>s.4]=rrqdCs8Td\
-q#:=7rVlu-g]&;mrrZWAruM+="hQ>*s56$;rrMt]rVm'jfDkm'J&M6a!K<->rrLn@rVlmLnFlk_
-F/f':!Gf"?rrTbe_>aH7*W?!>Y(H0ArrI#?rVlnkI/a-Ln1=V>H_UH<%Zl\M39B$\s+cm>s7pM$
-rr3*hf`1-5rr3%hJc>$9#9s$Ef"(g]jSo/[Uj;b8!CPQ>rrJ=@pAY3]K!G:S!U_T4rr=)=rrIk@
-rr3)N8",&.rt!@Ns1?e\ruV3<FoP7^p*Tb<"%Ur10E(nQ52PB[rVlngoC`+a?bQC;!kWsAr;Qi-
-J*-\/!jdLEJcDGDJ,~>
-#38'Ps0mL>qYpS^L@bEGqBGn<!DCl?rrJR?rr3&lJuSbL!BP?%rs4IFs"Wj>s.4]=rrqdCs8Td\
-q#:=7rVlu-g]&;mrrZWAruM+="hQ>*s56$;rrMt]rVm'jfDkm'J&M6a!K<->rrLn@rVlmLnFlk_
-F/f':!Gf"?rrTbe_>aH7*W?!>Y(H0ArrI#?rVlnkI/a-Ln1=V>H_UH<%Zl\M39B$\s+cm>s7pM$
-rr3*hf`1-5rr3%hJc>$9#9s$Ef"(g]jSo/[Uj;b8!CPQ>rrJ=@pAY3]K!G:S!U_T4rr=)=rrIk@
-rr3)N8",&.rt!@Ns1?e\ruV3<FoP7^p*Tb<"%Ur10E(nQ52PB[rVlngoC`+a?bQC;!kWsAr;Qi-
-J*-\/!jdLEJcDGDJ,~>
-#38'Ps0mL>qYpS^L@bEGqBGn<!DCl?rrJR?rr3&lJuSbL!BP?%rs4IFs"Wj>s.4]=rrqdCs8Td\
-q#:=7rVlu-g]&;mrrZWAruM+="hQ>*s56$;rrMt]rVm'jfDkm'J&M6a!K<->rrLn@rVlmLnFlk_
-F/f':!Gf"?rrTbe_>aH7*W?!>Y(H0ArrI#?rVlnkI/a-Ln1=V>H_UH<%Zl\M39B$\s+cm>s7pM$
-rr3*hf`1-5rr3%hJc>$9#9s$Ef"(g]jSo/[Uj;b8!CPQ>rrJ=@pAY3]K!G:S!U_T4rr=)=rrIk@
-rr3)N8",&.rt!@Ns1?e\ruV3<FoP7^p*Tb<"%Ur10E(nQ52PB[rVlngoC`+a?bQC;!kWsAr;Qi-
-J*-\/!jdLEJcDGDJ,~>
-"lqsOs(t7(Ad+k-s,iH?o`#2OA.E4Bs8TQHral1Wc2R_Ekl=QZrrG0:ralakeGlXcAnH==_uKc3
-OCi*Ug\CdKUA\[+K]2qOrVlt,^&OGuAd*cC`rFsZr;QfpOo8kmMspZF!L8H=rs7Fm3'([/s7)'H
-Ac\"hq#:rOAhHJ`n,NF0Ah-A`o`)KaJ,X$[TDeck=odLZrrI#?rVloOJGs-aBrh:6H_UH<%Zl\M
-YOp^8s3H%(AnZ`brr3,.DJ!jtrVlm>rp9XiVe9Uc`rEYjral1UanYl:6eVJ=!L&E7rrUmS@/^*+
-mOn/3!2BI)!IiSurr_\IHHlEg&*o'aK&$D+P@d08Ar5jNOo8koMsgA%rFQ.ko(A%AAc[qbp&>&"
-^&7m2FK#*:!Go%<rrQ[1eq*jps*t~>
-"lqsOs(t7(Ad+k-s,iH?o`#2OA.E4Bs8TQHral1Wc2R_Ekl=QZrrG0:ralakeGlXcAnH==_uKc3
-OCi*Ug\CdKUA\[+K]2qOrVlt,^&OGuAd*cC`rFsZr;QfpOo8kmMspZF!L8H=rs7Fm3'([/s7)'H
-Ac\"hq#:rOAhHJ`n,NF0Ah-A`o`)KaJ,X$[TDeck=odLZrrI#?rVloOJGs-aBrh:6H_UH<%Zl\M
-YOp^8s3H%(AnZ`brr3,.DJ!jtrVlm>rp9XiVe9Uc`rEYjral1UanYl:6eVJ=!L&E7rrUmS@/^*+
-mOn/3!2BI)!IiSurr_\IHHlEg&*o'aK&$D+P@d08Ar5jNOo8koMsgA%rFQ.ko(A%AAc[qbp&>&"
-^&7m2FK#*:!Go%<rrQ[1eq*jps*t~>
-"lqsOs(t7(Ad+k-s,iH?o`#2OA.E4Bs8TQHral1Wc2R_Ekl=QZrrG0:ralakeGlXcAnH==_uKc3
-OCi*Ug\CdKUA\[+K]2qOrVlt,^&OGuAd*cC`rFsZr;QfpOo8kmMspZF!L8H=rs7Fm3'([/s7)'H
-Ac\"hq#:rOAhHJ`n,NF0Ah-A`o`)KaJ,X$[TDeck=odLZrrI#?rVloOJGs-aBrh:6H_UH<%Zl\M
-YOp^8s3H%(AnZ`brr3,.DJ!jtrVlm>rp9XiVe9Uc`rEYjral1UanYl:6eVJ=!L&E7rrUmS@/^*+
-mOn/3!2BI)!IiSurr_\IHHlEg&*o'aK&$D+P@d08Ar5jNOo8koMsgA%rFQ.ko(A%AAc[qbp&>&"
-^&7m2FK#*:!Go%<rrQ[1eq*jps*t~>
-"QVjNs4.%T"O[8Lb4G6)!6+rF!7:`F!5e`C!7LiG!r97Jrr3![ir6=cfDbdR]=#&og>`,3"nB".
-h#DQp8cls2rVa,+iW&qlrVluIm/Qn\[0>C3mf3"#qu6ZgrNuXkrVlrWI)#[\!:Tlo"7Z?jm/=<m
-o(DiO!rDr[rNub%s8V3Z[06@+ldFMd[/g.'rrUNSpAP!le`Zl1!8IL\!4i+/!SQQ3rrM$6rr3;u
-a8c1h[C*O9ao25@^pV)XrrKi?li.$p[E\^N!6+rF!7:K?!Qk!5rrM'6pAY3dL1'u["RZ^k8u_Rb
-!<2u*!8.5L!UA,1rrVDlh>[E[p9f'B[HRYjo_l0"li7"TrNuaps8VQd[/f[irrgP<8fYPCrrTHY
-k5>5\X,-!:rrUWVo7?q8s*t~>
-"QVjNs4.%T"O[8Lb4G6)!6+rF!7:`F!5e`C!7LiG!r97Jrr3![ir6=cfDbdR]=#&og>`,3"nB".
-h#DQp8cls2rVa,+iW&qlrVluIm/Qn\[0>C3mf3"#qu6ZgrNuXkrVlrWI)#[\!:Tlo"7Z?jm/=<m
-o(DiO!rDr[rNub%s8V3Z[06@+ldFMd[/g.'rrUNSpAP!le`Zl1!8IL\!4i+/!SQQ3rrM$6rr3;u
-a8c1h[C*O9ao25@^pV)XrrKi?li.$p[E\^N!6+rF!7:K?!Qk!5rrM'6pAY3dL1'u["RZ^k8u_Rb
-!<2u*!8.5L!UA,1rrVDlh>[E[p9f'B[HRYjo_l0"li7"TrNuaps8VQd[/f[irrgP<8fYPCrrTHY
-k5>5\X,-!:rrUWVo7?q8s*t~>
-"QVjNs4.%T"O[8Lb4G6)!6+rF!7:`F!5e`C!7LiG!r97Jrr3![ir6=cfDbdR]=#&og>`,3"nB".
-h#DQp8cls2rVa,+iW&qlrVluIm/Qn\[0>C3mf3"#qu6ZgrNuXkrVlrWI)#[\!:Tlo"7Z?jm/=<m
-o(DiO!rDr[rNub%s8V3Z[06@+ldFMd[/g.'rrUNSpAP!le`Zl1!8IL\!4i+/!SQQ3rrM$6rr3;u
-a8c1h[C*O9ao25@^pV)XrrKi?li.$p[E\^N!6+rF!7:K?!Qk!5rrM'6pAY3dL1'u["RZ^k8u_Rb
-!<2u*!8.5L!UA,1rrVDlh>[E[p9f'B[HRYjo_l0"li7"TrNuaps8VQd[/f[irrgP<8fYPCrrTHY
-k5>5\X,-!:rrUWVo7?q8s*t~>
-!ouXLd/O,-ip?[Fh##J!nC@O>kO7p?!;u]@!<0,#!7o'f!PDh=rrDurd/`FerrK$?h>[KGrm:`;
-rVloalMLS^lKj*%QiDR~>
-!ouXLd/O,-ip?[Fh##J!nC@O>kO7p?!;u]@!<0,#!7o'f!PDh=rrDurd/`FerrK$?h>[KGrm:`;
-rVloalMLS^lKj*%QiDR~>
-!ouXLd/O,-ip?[Fh##J!nC@O>kO7p?!;u]@!<0,#!7o'f!PDh=rrDurd/`FerrK$?h>[KGrm:`;
-rVloalMLS^lKj*%QiDR~>
-!ouXLd/O,5jFR>grrV%Uo[NmAWdB<sJcF[.J,~>
-!ouXLd/O,5jFR>grrV%Uo[NmAWdB<sJcF[.J,~>
-!ouXLd/O,5jFR>grrV%Uo[NmAWdB<sJcF[.J,~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-#in9Rs8UK[]uSt/!65#O!82r'JcC<$JcE(VJ,~>
-#in9Rs8UK[]uSt/!65#O!82r'JcC<$JcE(VJ,~>
-#in9Rs8UK[]uSt/!65#O!82r'JcC<$JcE(VJ,~>
-$04BSs2f=g?>-n,rrKZDra#VPe:IXNs+13$s0VfV~>
-$04BSs2f=g?>-n,rrKZDra#VPe:IXNs+13$s0VfV~>
-$04BSs2f=g?>-n,rrKZDra#VPe:IXNs+13$s0VfV~>
-$04BSs)#"?s4Kcsrs#$Hqu?]9_L_`<s+13$s0VfV~>
-$04BSs)#"?s4Kcsrs#$Hqu?]9_L_`<s+13$s0VfV~>
-$04BSs)#"?s4Kcsrs#$Hqu?]9_L_`<s+13$s0VfV~>
-%HKfWs)#"?s4Kd>s.n3ErrLQFrr3"HrVca&Rc"$ks2_GEs+C;b!2TVo"=7VnBrV+3!."QX!3UnQ
-JcC<$JcE@^J,~>
-%HKfWs)#"?s4Kd>s.n3ErrLQFrr3"HrVca&Rc"$ks2_GEs+C;b!2TVo"=7VnBrV+3!."QX!3UnQ
-JcC<$JcE@^J,~>
-%HKfWs)#"?s4Kd>s.n3ErrLQFrr3"HrVca&Rc"$ks2_GEs+C;b!2TVo"=7VnBrV+3!."QX!3UnQ
-JcC<$JcE@^J,~>
-%HKfWs(sVe9L2&Gs(&Y=rrKK@rr3!Bqu-O$;p"k[s.ao?JY<"K"H'/XH_gYI"Ga/[Ff55F!J@_0
-s+13$s+13_s*t~>
-%HKfWs(sVe9L2&Gs(&Y=rrKK@rr3!Bqu-O$;p"k[s.ao?JY<"K"H'/XH_gYI"Ga/[Ff55F!J@_0
-s+13$s+13_s*t~>
-%HKfWs(sVe9L2&Gs(&Y=rrKK@rr3!Bqu-O$;p"k[s.ao?JY<"K"H'/XH_gYI"Ga/[Ff55F!J@_0
-s+13$s+13_s*t~>
-'')>\s)!eBc`fe:s5I;>s4Ui>rr3!Bqu-O$;p"k[s.ao?9@Eh>"IarB6JDG="Hn]C3o^/=!U8m#
-s+13$s+13_s*t~>
-'')>\s)!eBc`fe:s5I;>s4Ui>rr3!Bqu-O$;p"k[s.ao?9@Eh>"IarB6JDG="Hn]C3o^/=!U8m#
-s+13$s+13_s*t~>
-'')>\s)!eBc`fe:s5I;>s4Ui>rr3!Bqu-O$;p"k[s.ao?9@Eh>"IarB6JDG="Hn]C3o^/=!U8m#
-s+13$s+13_s*t~>
-$04BSs)#"?s4Kd=rrc$Brle7<rrF;?rVm1&and4]UO)r5df07LRY(Q+gA_*WP)KA)1)q9LJcC<$
-JcC<$])R9~>
-$04BSs)#"?s4Kd=rrc$Brle7<rrF;?rVm1&and4]UO)r5df07LRY(Q+gA_*WP)KA)1)q9LJcC<$
-JcC<$])R9~>
-$04BSs)#"?s4Kd=rrc$Brle7<rrF;?rVm1&and4]UO)r5df07LRY(Q+gA_*WP)KA)1)q9LJcC<$
-JcC<$])R9~>
-$04BSs)#"?s4Kd<rrO\00)Y_[+oD#ss8Q$>qBGs7HN-Xdrr3+iK)\0krr3+aMuPitrr3#fn:CUj
-s+13$s1JA^~>
-$04BSs)#"?s4Kd<rrO\00)Y_[+oD#ss8Q$>qBGs7HN-Xdrr3+iK)\0krr3+aMuPitrr3#fn:CUj
-s+13$s1JA^~>
-$04BSs)#"?s4Kd<rrO\00)Y_[+oD#ss8Q$>qBGs7HN-Xdrr3+iK)\0krr3+aMuPitrr3#fn:CUj
-s+13$s1JA^~>
-$04BSs,i\`^T;JSrrQQ4@f66:=hUV\s8RPD]G\JHS,[`4rkASqU&T,7rkASmW;gY<rkAJeY(?V(
-s+13$s1JA^~>
-$04BSs,i\`^T;JSrrQQ4@f66:=hUV\s8RPD]G\JHS,[`4rkASqU&T,7rkASmW;gY<rkAJeY(?V(
-s+13$s1JA^~>
-$04BSs,i\`^T;JSrrQQ4@f66:=hUV\s8RPD]G\JHS,[`4rkASqU&T,7rkASmW;gY<rkAJeY(?V(
-s+13$s1JA^~>
-#in9Rs8S-b>]flC!,q`6!FC9SrrddS$s].urr@?D>QC;nrr@0?>QCMtrr?s9>QC[Qs+13$s+13^
-s*t~>
-#in9Rs8S-b>]flC!,q`6!FC9SrrddS$s].urr@?D>QC;nrr@0?>QCMtrr?s9>QC[Qs+13$s+13^
-s*t~>
-#in9Rs8S-b>]flC!,q`6!FC9SrrddS$s].urr@?D>QC;nrr@0?>QCMtrr?s9>QC[Qs+13$s+13^
-s*t~>
-!ouXLk5PJY,(]cFs+13$s.TIC~>
-!ouXLk5PJY,(]cFs+13$s.TIC~>
-!ouXLk5PJY,(]cFs+13$s.TIC~>
-!ouXLk5PJY,(]cFs+13$s.TIC~>
-!ouXLk5PJY,(]cFs+13$s.TIC~>
-!ouXLk5PJY,(]cFs+13$s.TIC~>
-!ouXLk5PJ]\q0m4s+13$s.TIC~>
-!ouXLk5PJ]\q0m4s+13$s.TIC~>
-!ouXLk5PJ]\q0m4s+13$s.TIC~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLq#:A8^4H<8s+13$s,[21~>
-!ouXLq#:A8^4H<8s+13$s,[21~>
-!ouXLq#:A8^4H<8s+13$s,[21~>
-!ouXLq#:A*\:O[2s+13$s,[21~>
-!ouXLq#:A*\:O[2s+13$s,[21~>
-!ouXLq#:A*\:O[2s+13$s,[21~>
-"lqsOs8UXK_?A<es(&Y=rrMNAJcC<$JcC<$PlH7~>
-"lqsOs8UXK_?A<es(&Y=rrMNAJcC<$JcC<$PlH7~>
-"lqsOs8UXK_?A<es(&Y=rrMNAJcC<$JcC<$PlH7~>
-"lqsOs3,K^=UArcs(&Y>q504DJcC<$JcC<$PlH7~>
-"lqsOs3,K^=UArcs(&Y>q504DJcC<$JcC<$PlH7~>
-"lqsOs3,K^=UArcs(&Y>q504DJcC<$JcC<$PlH7~>
-"lqsOs)#">rs68Fs(&X1Lio;?s+13$s+136s*t~>
-"lqsOs)#">rs68Fs(&X1Lio;?s+13$s+136s*t~>
-"lqsOs)#">rs68Fs(&X1Lio;?s+13$s+136s*t~>
-"lqsOs)#">rs$,Ds("oaR=YBhs+13$s,m>3~>
-"lqsOs)#">rs$,Ds("oaR=YBhs+13$s,m>3~>
-"lqsOs)#">rs$,Ds("oaR=YBhs+13$s,m>3~>
-"lqsOs)#">rs$,Ds($Od?%N$,s+13$s,m>3~>
-"lqsOs)#">rs$,Ds($Od?%N$,s+13$s,m>3~>
-"lqsOs)#">rs$,Ds($Od?%N$,s+13$s,m>3~>
-"lqsOs)#">rs68Fs(&Xf^c$1`s+13$s+136s*t~>
-"lqsOs)#">rs68Fs(&Xf^c$1`s+13$s+136s*t~>
-"lqsOs)#">rs68Fs(&Xf^c$1`s+13$s+136s*t~>
-"lqsOs6s7l*!oL2s(8hArT1&)JcC<$JcC<$PlH7~>
-"lqsOs6s7l*!oL2s(8hArT1&)JcC<$JcC<$PlH7~>
-"lqsOs6s7l*!oL2s(8hArT1&)JcC<$JcC<$PlH7~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-!ouXLJcC<$JcC<$K`?Q~>
-"QVjNs/l3<"K)5!R-9,$JcC<$JcCi3J,~>
-"QVjNs/l3<"K)5!R-9,$JcC<$JcCi3J,~>
-"QVjNs/l3<"K)5!R-9,$JcC<$JcCi3J,~>
-"QVjNs3LYE#(Bt[s2&7>JcC<$JcC<$OoKq~>
-"QVjNs3LYE#(Bt[s2&7>JcC<$JcC<$OoKq~>
-"QVjNs3LYE#(Bt[s2&7>JcC<$JcC<$OoKq~>
-!ouXLr;QiX?JPP[!ROMks+13$s+134s*t~>
-!ouXLr;QiX?JPP[!ROMks+13$s+134s*t~>
-!ouXLr;QiX?JPP[!ROMks+13$s+134s*t~>
-!ouXLrVlrn3U6PB!S9bks+13$s+135s*t~>
-!ouXLrVlrn3U6PB!S9bks+13$s+135s*t~>
-!ouXLrVlrn3U6PB!S9bks+13$s+135s*t~>
-%%EndData
-showpage
-%%Trailer
-end
-%%EOF
diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml
index cf0d581352..61f49f5940 100644
--- a/lib/stdlib/doc/src/zip.xml
+++ b/lib/stdlib/doc/src/zip.xml
@@ -217,7 +217,7 @@
<tag><c>{uncompress, <anno>What</anno>}</c></tag>
<item>
<p>Controls what types of files will be uncompressed. It is by
- default set to <c>[".Z",".zip",".zoo",".arc",".lzh",".arj"]</c>.
+ default set to <c>[".Z", ".zip", ".zoo", ".arc", ".lzh", ".arj"]</c>.
The following values of <c>What</c> are allowed:</p>
<taglist>
<tag><c>all</c></tag>
@@ -355,7 +355,7 @@
{ok,{"dummy.zip",
&lt;&lt;80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,
0,0,3,0,0,...&gt;&gt;}}
-&gt; <input>catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_, _, _, Acc) -> Acc end, [], {Name, Bin}). </input>
+&gt; <input>catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}). </input>
&lt;&lt;"FOO"&gt;&gt;
</pre>
</desc>
diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile
index 14304824d3..575a5cbe4a 100644
--- a/lib/stdlib/src/Makefile
+++ b/lib/stdlib/src/Makefile
@@ -171,6 +171,7 @@ primary_bootstrap_compiler: \
$(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
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index a920921a5e..4c1c0f904b 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -116,7 +116,7 @@ machine_load(Mod, File, Opts) ->
File2 = filename:join(Dir, filename:basename(File, ".erl")),
case compile:output_generated(Opts) of
true ->
- Base = packages:last(Mod),
+ Base = atom_to_list(Mod),
case filename:basename(File, ".erl") of
Base ->
code:purge(Mod),
diff --git a/lib/stdlib/src/dict.erl b/lib/stdlib/src/dict.erl
index 2e9eba4bfa..4f8d45dc8d 100644
--- a/lib/stdlib/src/dict.erl
+++ b/lib/stdlib/src/dict.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -17,7 +18,7 @@
%% %CopyrightEnd%
%%
-%% We use the dynamic hashing techniques by Per-�ke Larsson as
+%% We use the dynamic hashing techniques by Per-Åke Larsson as
%% described in "The Design and Implementation of Dynamic Hashing for
%% Sets and Tables in Icon" by Griswold and Townsend. Much of the
%% terminology comes from that paper as well.
diff --git a/lib/stdlib/src/edlin.erl b/lib/stdlib/src/edlin.erl
index 026bd9038f..1164ee49eb 100644
--- a/lib/stdlib/src/edlin.erl
+++ b/lib/stdlib/src/edlin.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -317,9 +318,9 @@ over_non_word([], Stack, N) ->
{[],Stack,N}.
word_char(C) when C >= $A, C =< $Z -> true;
-word_char(C) when C >= $�, C =< $�, C =/= $� -> true;
+word_char(C) when C >= $À, C =< $Þ, C =/= $× -> true;
word_char(C) when C >= $a, C =< $z -> true;
-word_char(C) when C >= $�, C =< $�, C =/= $� -> true;
+word_char(C) when C >= $ß, C =< $ÿ, C =/= $÷ -> true;
word_char(C) when C >= $0, C =< $9 -> true;
word_char(C) when C =:= $_ -> true;
word_char(C) when C =:= $. -> true; % accept dot-separated names
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 2c8d84a9e1..a0f7660ecf 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -23,13 +23,18 @@
-export([open/2,open/3,open/5,close/1,format_error/1]).
-export([scan_erl_form/1,parse_erl_form/1,macro_defs/1]).
-export([parse_file/1, parse_file/3]).
+-export([default_encoding/0, encoding_to_string/1,
+ read_encoding/1, read_encoding/2, set_encoding/1]).
-export([interpret_file_attribute/1]).
-export([normalize_typed_record_fields/1,restore_typed_record_fields/1]).
%%------------------------------------------------------------------------
+-export_type([source_encoding/0]).
+
-type macros() :: [{atom(), term()}].
-type epp_handle() :: pid().
+-type source_encoding() :: latin1 | utf8.
%% Epp state record.
-record(epp, {file, %Current file
@@ -213,6 +218,173 @@ parse_file(Epp) ->
[{eof,Location}]
end.
+-define(DEFAULT_ENCODING, latin1).
+
+-spec default_encoding() -> source_encoding().
+
+default_encoding() ->
+ ?DEFAULT_ENCODING.
+
+-spec encoding_to_string(Encoding) -> string() when
+ Encoding :: source_encoding().
+
+encoding_to_string(latin1) -> "coding: latin-1";
+encoding_to_string(utf8) -> "coding: utf-8".
+
+-spec read_encoding(FileName) -> source_encoding() | none when
+ FileName :: file:name().
+
+read_encoding(Name) ->
+ read_encoding(Name, []).
+
+-spec read_encoding(FileName, Options) -> source_encoding() | none when
+ FileName :: file:name(),
+ Options :: [Option],
+ Option :: {in_comment_only, boolean()}.
+
+read_encoding(Name, Options) ->
+ InComment = proplists:get_value(in_comment_only, Options, true),
+ case file:open(Name, [read]) of
+ {ok,File} ->
+ try read_encoding_from_file(File, InComment)
+ after ok = file:close(File)
+ end;
+ _Error ->
+ none
+ end.
+
+-spec set_encoding(File) -> source_encoding() | none when
+ File :: io:device(). % pid(); raw files don't work
+
+set_encoding(File) ->
+ Encoding = read_encoding_from_file(File, true),
+ Enc = case Encoding of
+ none -> default_encoding();
+ Encoding -> Encoding
+ end,
+ ok = io:setopts(File, [{encoding, Enc}]),
+ Encoding.
+
+-spec read_encoding_from_file(File, InComment) -> source_encoding() | none when
+ File :: io:device(),
+ InComment :: boolean().
+
+-define(ENC_CHUNK, 32).
+-define(N_ENC_CHUNK, 16). % a total of 512 bytes
+
+read_encoding_from_file(File, InComment) ->
+ {ok, Pos0} = file:position(File, cur),
+ Opts = io:getopts(File),
+ Encoding0 = lists:keyfind(encoding, 1, Opts),
+ Binary0 = lists:keyfind(binary, 1, Opts),
+ ok = io:setopts(File, [binary, {encoding, latin1}]),
+ try
+ {B, Fun} = (reader(File, 0))(),
+ com_nl(B, Fun, 0, InComment)
+ catch
+ throw:no ->
+ none
+ after
+ {ok, Pos0} = file:position(File, Pos0),
+ ok = io:setopts(File, [Binary0, Encoding0])
+ end.
+
+reader(Fd, N) ->
+ fun() when N =:= ?N_ENC_CHUNK ->
+ throw(no);
+ () ->
+ case file:read(Fd, ?ENC_CHUNK) of
+ eof ->
+ {<<>>, reader(Fd, N+1)};
+ {ok, Bin} ->
+ {Bin, reader(Fd, N+1)};
+ {error, _} ->
+ throw(no) % ignore errors
+ end
+ end.
+
+com_nl(_, _, 2, _) ->
+ throw(no);
+com_nl(B, Fun, N, false=Com) ->
+ com_c(B, Fun, N, Com);
+com_nl(B, Fun, N, true=Com) ->
+ com(B, Fun, N, Com).
+
+com(<<"\n",B/binary>>, Fun, N, Com) ->
+ com_nl(B, Fun, N+1, Com);
+com(<<"%", B/binary>>, Fun, N, Com) ->
+ com_c(B, Fun, N, Com);
+com(<<_:1/unit:8,B/binary>>, Fun, N, Com) ->
+ com(B, Fun, N, Com);
+com(<<>>, Fun, N, Com) ->
+ {B, Fun1} = Fun(),
+ com(B, Fun1, N, Com).
+
+com_c(<<"c",B/binary>>, Fun, N, Com) ->
+ com_oding(B, Fun, N, Com);
+com_c(<<"\n",B/binary>>, Fun, N, Com) ->
+ com_nl(B, Fun, N+1, Com);
+com_c(<<_:1/unit:8,B/binary>>, Fun, N, Com) ->
+ com_c(B, Fun, N, Com);
+com_c(<<>>, Fun, N, Com) ->
+ {B, Fun1} = Fun(),
+ com_c(B, Fun1, N, Com).
+
+com_oding(<<"oding",B/binary>>, Fun, N, Com) ->
+ com_sep(B, Fun, N, Com);
+com_oding(B, Fun, N, Com) when byte_size(B) >= length("oding") ->
+ com_c(B, Fun, N, Com);
+com_oding(B, Fun, N, Com) ->
+ {B1, Fun1} = Fun(),
+ com_oding(list_to_binary([B, B1]), Fun1, N, Com).
+
+com_sep(<<":",B/binary>>, Fun, N, Com) ->
+ com_space(B, Fun, N, Com);
+com_sep(<<"=",B/binary>>, Fun, N, Com) ->
+ com_space(B, Fun, N, Com);
+com_sep(<<"\s",B/binary>>, Fun, N, Com) ->
+ com_sep(B, Fun, N, Com);
+com_sep(<<>>, Fun, N, Com) ->
+ {B, Fun1} = Fun(),
+ com_sep(B, Fun1, N, Com);
+com_sep(B, Fun, N, Com) ->
+ com_c(B, Fun, N, Com).
+
+com_space(<<"\s",B/binary>>, Fun, N, Com) ->
+ com_space(B, Fun, N, Com);
+com_space(<<>>, Fun, N, Com) ->
+ {B, Fun1} = Fun(),
+ com_space(B, Fun1, N, Com);
+com_space(B, Fun, N, _Com) ->
+ com_enc(B, Fun, N, [], []).
+
+com_enc(<<C:1/unit:8,B/binary>>, Fun, N, L, Ps) when C >= $a, C =< $z;
+ C >= $A, C =< $Z;
+ C >= $0, C =< $9 ->
+ com_enc(B, Fun, N, [C | L], Ps);
+com_enc(<<>>, Fun, N, L, Ps) ->
+ case Fun() of
+ {<<>>, _} ->
+ com_enc_end([L | Ps]);
+ {B, Fun1} ->
+ com_enc(B, Fun1, N, L, Ps)
+ end;
+com_enc(<<"-",B/binary>>, Fun, N, L, Ps) ->
+ com_enc(B, Fun, N, [], [L | Ps]);
+com_enc(_B, _Fun, _N, L, Ps) ->
+ com_enc_end([L | Ps]).
+
+com_enc_end(Ps0) ->
+ Ps = lists:reverse([lists:reverse(string:to_lower(P)) || P <- Ps0]),
+ com_encoding(Ps).
+
+com_encoding(["latin","1"|_]) ->
+ latin1;
+com_encoding(["utf","8"|_]) ->
+ utf8;
+com_encoding(_) ->
+ throw(no). % Don't try any further
+
normalize_typed_record_fields([]) ->
{typed, []};
normalize_typed_record_fields(Fields) ->
@@ -266,14 +438,17 @@ init_server(Pid, Name, File, AtLocation, Path, Pdm, Pre) ->
Ms0 = predef_macros(Name),
case user_predef(Pdm, Ms0) of
{ok,Ms1} ->
- epp_reply(Pid, {ok,self()}),
- %% ensure directory of current source file is first in path
+ _ = set_encoding(File),
+ epp_reply(Pid, {ok,self()}),
+ %% ensure directory of current source file is
+ %% first in path
Path1 = [filename:dirname(Name) | Path],
- St = #epp{file=File, location=AtLocation, delta=0, name=Name,
- name2=Name, path=Path1, macs=Ms1, pre_opened = Pre},
- From = wait_request(St),
- enter_file_reply(From, Name, AtLocation, AtLocation),
- wait_req_scan(St);
+ St = #epp{file=File, location=AtLocation, delta=0,
+ name=Name, name2=Name, path=Path1, macs=Ms1,
+ pre_opened = Pre},
+ From = wait_request(St),
+ enter_file_reply(From, Name, AtLocation, AtLocation),
+ wait_req_scan(St);
{error,E} ->
epp_reply(Pid, {error,E})
end.
@@ -385,19 +560,20 @@ enter_file(NewName, Inc, From, St) ->
%% enter_file2(File, FullName, From, EppState, AtLocation) -> EppState.
%% Set epp to use this file and "enter" it.
-enter_file2(NewF, Pname, From, St, AtLocation) ->
+enter_file2(NewF, Pname, From, St0, AtLocation) ->
Loc = start_loc(AtLocation),
enter_file_reply(From, Pname, Loc, AtLocation),
- Ms = dict:store({atom,'FILE'}, {none,[{string,Loc,Pname}]}, St#epp.macs),
+ Ms = dict:store({atom,'FILE'}, {none,[{string,Loc,Pname}]}, St0#epp.macs),
%% update the head of the include path to be the directory of the new
%% source file, so that an included file can always include other files
%% relative to its current location (this is also how C does it); note
%% that the directory of the parent source file (the previous head of
%% the path) must be dropped, otherwise the path used within the current
%% file will depend on the order of file inclusions in the parent files
- Path = [filename:dirname(Pname) | tl(St#epp.path)],
+ Path = [filename:dirname(Pname) | tl(St0#epp.path)],
+ _ = set_encoding(NewF),
#epp{file=NewF,location=Loc,name=Pname,delta=0,
- sstk=[St|St#epp.sstk],path=Path,macs=Ms}.
+ sstk=[St0|St0#epp.sstk],path=Path,macs=Ms}.
enter_file_reply(From, Name, Location, AtLocation) ->
Attr = loc_attr(AtLocation),
@@ -456,7 +632,7 @@ 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
+ case io:scan_erl_form(St#epp.file, '', St#epp.location, [unicode]) of
{ok,Toks,Cl} ->
scan_toks(Toks, From, St#epp{location=Cl});
{error,E,Cl} ->
@@ -830,7 +1006,7 @@ 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
+ case io:scan_erl_form(St#epp.file, '', St#epp.location, [unicode]) of
{ok,[{'-',_Lh},{atom,_Li,ifdef}|_Toks],Cl} ->
skip_toks(From, St#epp{location=Cl}, [ifdef,I|Sis]);
{ok,[{'-',_Lh},{atom,_Li,ifndef}|_Toks],Cl} ->
@@ -1094,6 +1270,7 @@ expand_arg([], Ts, L, Rest, Bs) ->
%%% tokenized would yield the token list Ts.
%% erl_scan:token_info(T, text) is not backward compatible with this.
+%% Note that escaped characters will be replaced by themselves.
token_src({dot, _}) ->
".";
token_src({X, _}) when is_atom(X) ->
@@ -1101,16 +1278,16 @@ token_src({X, _}) when is_atom(X) ->
token_src({var, _, X}) ->
atom_to_list(X);
token_src({char,_,C}) ->
- io_lib:write_char(C);
+ io_lib:write_unicode_char(C);
token_src({string, _, X}) ->
- lists:flatten(io_lib:format("~p", [X]));
+ io_lib:write_unicode_string(X);
token_src({_, _, X}) ->
- lists:flatten(io_lib:format("~w", [X])).
+ io_lib:format("~w", [X]).
stringify1([]) ->
[];
stringify1([T | Tokens]) ->
- [io_lib:format(" ~s", [token_src(T)]) | stringify1(Tokens)].
+ [io_lib:format(" ~ts", [token_src(T)]) | stringify1(Tokens)].
stringify(Ts, L) ->
[$\s | S] = lists:flatten(stringify1(Ts)),
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 95ba6b1096..8471ae6b64 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -227,13 +227,6 @@ expr({bc,_,E,Qs}, Bs, Lf, Ef, RBs) ->
expr({tuple,_,Es}, Bs0, Lf, Ef, RBs) ->
{Vs,Bs} = expr_list(Es, Bs0, Lf, Ef),
ret_expr(list_to_tuple(Vs), Bs, RBs);
-expr({record_field,_,_,_}=Mod, Bs, _Lf, _Ef, RBs) ->
- case expand_module_name(Mod, Bs) of
- {atom,_,A} ->
- ret_expr(A, Bs, RBs); %% This is the "x.y" syntax
- _ ->
- erlang:raise(error, {badexpr, '.'}, stacktrace())
- end;
expr({record_field,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
erlang:raise(error, {undef_record,Name}, stacktrace());
expr({record_index,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
@@ -332,8 +325,7 @@ expr({call,L1,{remote,L2,{record_field,_,{atom,_,''},{atom,_,qlc}=Mod},
Bs, Lf, Ef, RBs) when length(As0) =< 1 ->
expr({call,L1,{remote,L2,Mod,Func},As}, Bs, Lf, Ef, RBs);
expr({call,_,{remote,_,Mod,Func},As0}, Bs0, Lf, Ef, RBs) ->
- Mod1 = expand_module_name(Mod, Bs0),
- {value,M,Bs1} = expr(Mod1, Bs0, Lf, Ef, none),
+ {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),
%% M could be a parameterized module (not an atom).
@@ -1210,41 +1202,6 @@ ret_expr(_Old, New) ->
line(Expr) -> element(2, Expr).
-%% In syntax trees, module/package names are atoms or lists of atoms.
-
-expand_module_name({atom,L,A} = M, Bs) ->
- case binding({module,A}, Bs) of
- {value, A1} ->
- {atom,L,A1};
- unbound ->
- case packages:is_segmented(A) of
- true ->
- M;
- false ->
-%%% P = case binding({module,'$package'}, Bs) of
-%%% {value, P1} -> P1;
-%%% unbound -> ""
-%%% end,
-%%% A1 = list_to_atom(packages:concat(P, A)),
-%%% {atom,L,list_to_atom(A1)}
- {atom,L,A}
- end
- end;
-expand_module_name(M, _) ->
- case erl_parse:package_segments(M) of
- error ->
- M;
- M1 ->
- L = element(2,M),
- Mod = packages:concat(M1),
- case packages:is_valid(Mod) of
- true ->
- {atom,L,list_to_atom(Mod)};
- false ->
- erlang:raise(error, {bad_module_name, Mod}, stacktrace())
- end
- end.
-
%% {?MODULE,expr,3} is still the stacktrace, despite the
%% fact that expr() now takes two, three or four arguments...
stacktrace() -> [{?MODULE,expr,3}].
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index 85defacc43..d05f630d8e 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -135,8 +135,6 @@ pattern({tuple,Line,Ps}, St0) ->
%%pattern({struct,Line,Tag,Ps}, St0) ->
%% {TPs,TPsvs,St1} = pattern_list(Ps, St0),
%% {{struct,Line,Tag,TPs},TPsvs,St1};
-pattern({record_field,_,_,_}=M, St) ->
- {M,St}; % must be a package name
pattern({record_index,Line,Name,Field}, St) ->
{index_expr(Line, Field, Name, record_fields(Name, St)),St};
pattern({record,Line,Name,Pfs}, St0) ->
@@ -306,8 +304,6 @@ expr({tuple,Line,Es0}, St0) ->
%%expr({struct,Line,Tag,Es0}, Vs, St0) ->
%% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0),
%% {{struct,Line,Tag,Es1},Esvs,Esus,St1};
-expr({record_field,_,_,_}=M, St) ->
- {M,St}; % must be a package name
expr({record_index,Line,Name,F}, St) ->
I = index_expr(Line, F, Name, record_fields(Name, St)),
expr(I, St);
@@ -375,9 +371,6 @@ expr({call,Line,{atom,_La,N}=Atom,As0}, St0) ->
end
end
end;
-expr({call,Line,{record_field,_,_,_}=M,As0}, St0) ->
- {As,St1} = expr_list(As0, St0),
- {{call,Line,M,As},St1};
expr({call,Line,{remote,Lr,M,F},As0}, St0) ->
{[M1,F1 | As1],St1} = expr_list([M,F | As0], St0),
{{call,Line,{remote,Lr,M1,F1},As1},St1};
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 1e5f962375..d24e2fff44 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -94,12 +94,10 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
%% the other function collections contain {Function, Arity}.
-record(lint, {state=start :: 'start' | 'attribute' | 'function',
module=[], %Module
- package="", %Module package
extends=[], %Extends
behaviour=[], %Behaviour
exports=gb_sets:empty() :: gb_set(), %Exports
imports=[], %Imports
- mod_imports=dict:new() :: dict(), %Module Imports
compile=[], %Compile flags
records=dict:new() :: dict(), %Record definitions
locals=gb_sets:empty() :: gb_set(), %All defined functions (prescanned)
@@ -539,7 +537,6 @@ start(File, Opts) ->
end,
#lint{state = start,
exports = gb_sets:from_list([{module_info,0},{module_info,1}]),
- mod_imports = dict:from_list([{erlang,erlang}]),
compile = Opts,
%% Internal pseudo-functions must appear as defined/reached.
defined = gb_sets:from_list(pseudolocals()),
@@ -681,8 +678,8 @@ form(Form, #lint{state=State}=St) ->
%% start_state(Form, State) -> State'
-start_state({attribute,L,module,{M,Ps}}, St) ->
- St1 = set_module(M, L, St),
+start_state({attribute,_,module,{M,Ps}}, St0) ->
+ St1 = St0#lint{module=M},
Arity = length(Ps),
Ps1 = if is_atom(St1#lint.extends) ->
['BASE', 'THIS' | Ps];
@@ -693,23 +690,13 @@ start_state({attribute,L,module,{M,Ps}}, St) ->
St2 = add_instance(Arity, St1),
St3 = ensure_new(Arity, St2),
St3#lint{state=attribute, extends=[], global_vt=Vt};
-start_state({attribute,L,module,M}, St) ->
- St1 = set_module(M, L, St),
+start_state({attribute,_,module,M}, St0) ->
+ St1 = St0#lint{module=M},
St1#lint{state=attribute, extends=[]};
start_state(Form, St) ->
St1 = add_error(element(2, Form), undefined_module, St),
attribute_state(Form, St1#lint{state=attribute, extends=[]}).
-set_module(M, L, St) ->
- M1 = package_to_string(M),
- case packages:is_valid(M1) of
- true ->
- St#lint{module=list_to_atom(M1),
- package=packages:strip_last(M1)};
- false ->
- add_error(L, {bad_module_name, M1}, St)
- end.
-
ensure_new(Arity, St) ->
case St#lint.new of
true ->
@@ -1007,9 +994,9 @@ check_imports(Forms, St0) ->
true ->
Usage = St0#lint.usage,
Unused = ordsets:subtract(St0#lint.imports, Usage#usage.imported),
- Imports = [{{FA,list_to_atom(package_to_string(Mod))},L}
- || {attribute,L,import,{Mod,Fs}} <- Forms,
- FA <- lists:usort(Fs)],
+ Imports = [{{FA,Mod},L} ||
+ {attribute,L,import,{Mod,Fs}} <- Forms,
+ FA <- lists:usort(Fs)],
Bad = [{FM,L} || FM <- Unused, {FM2,L} <- Imports, FM =:= FM2],
func_line_warning(unused_import, Bad, St0)
end.
@@ -1222,73 +1209,46 @@ export_type(Line, ETs, #lint{usage = Usage, exp_types = ETs0} = St0) ->
-spec import(line(), import(), lint_state()) -> lint_state().
import(Line, {Mod,Fs}, St) ->
- Mod1 = package_to_string(Mod),
- case packages:is_valid(Mod1) of
- true ->
- Mfs = ordsets:from_list(Fs),
- case check_imports(Line, Mfs, St#lint.imports) of
- [] ->
- St#lint{imports=add_imports(list_to_atom(Mod1), Mfs,
- St#lint.imports)};
- Efs ->
- {Err, St1} =
- foldl(fun ({bif,{F,A},_}, {Err,St0}) ->
- %% BifClash - import directive
- Warn = is_warn_enabled(bif_clash, St0)
- and (not bif_clash_specifically_disabled(St0,{F,A})),
- AutoImpSup = is_autoimport_suppressed(St0#lint.no_auto,{F,A}),
- OldBif = erl_internal:old_bif(F,A),
- {Err,if
- Warn and (not AutoImpSup) and OldBif ->
- add_error
- (Line,
- {redefine_old_bif_import, {F,A}},
- St0);
- Warn and (not AutoImpSup) ->
- add_warning
- (Line,
- {redefine_bif_import, {F,A}},
- St0);
- true ->
- St0
- end};
- (Ef, {_Err,St0}) ->
- {true,add_error(Line,
- {redefine_import,Ef},
- St0)}
- end,
- {false,St}, Efs),
- if
- not Err ->
- St1#lint{imports=
- add_imports(list_to_atom(Mod1), Mfs,
+ Mfs = ordsets:from_list(Fs),
+ case check_imports(Line, Mfs, St#lint.imports) of
+ [] ->
+ St#lint{imports=add_imports(Mod, Mfs,
+ St#lint.imports)};
+ Efs ->
+ {Err, St1} =
+ foldl(fun ({bif,{F,A},_}, {Err,St0}) ->
+ %% BifClash - import directive
+ Warn = is_warn_enabled(bif_clash, St0) andalso
+ (not bif_clash_specifically_disabled(St0,{F,A})),
+ AutoImpSup = is_autoimport_suppressed(St0#lint.no_auto,{F,A}),
+ OldBif = erl_internal:old_bif(F,A),
+ {Err,if
+ Warn and (not AutoImpSup) and OldBif ->
+ add_error
+ (Line,
+ {redefine_old_bif_import, {F,A}},
+ St0);
+ Warn and (not AutoImpSup) ->
+ add_warning
+ (Line,
+ {redefine_bif_import, {F,A}},
+ St0);
+ true ->
+ St0
+ end};
+ (Ef, {_Err,St0}) ->
+ {true,add_error(Line,
+ {redefine_import,Ef},
+ St0)}
+ end,
+ {false,St}, Efs),
+ if
+ not Err ->
+ St1#lint{imports=add_imports(Mod, Mfs,
St#lint.imports)};
- true ->
- St1
- end
- end;
- false ->
- add_error(Line, {bad_module_name, Mod1}, St)
- end;
-import(Line, Mod, St) ->
- Mod1 = package_to_string(Mod),
- case packages:is_valid(Mod1) of
- true ->
- Key = list_to_atom(packages:last(Mod1)),
- Imps = St#lint.mod_imports,
-%%% case dict:is_key(Key, Imps) of
-%%% true ->
-%%% M = packages:last(Mod1),
-%%% P = packages:strip_last(Mod1),
-%%% add_error(Line, {redefine_mod_import, M, P}, St);
-%%% false ->
-%%% St#lint{mod_imports =
-%%% dict:store(Key, list_to_atom(Mod1), Imps)}
-%%% end;
- St#lint{mod_imports = dict:store(Key, list_to_atom(Mod1),
- Imps)};
- false ->
- add_error(Line, {bad_module_name, Mod1}, St)
+ true ->
+ St1
+ end
end.
check_imports(_Line, Fs, Is) ->
@@ -1463,13 +1423,6 @@ pattern({record_index,Line,Name,Field}, _Vt, _Old, _Bvt, St) ->
pattern_field(Field, Name, Dfs, St1)
end),
{Vt1,[],St1};
-pattern({record_field,Line,_,_}=M, _Vt, _Old, _Bvt, St0) ->
- case expand_package(M, St0) of
- {error, St1} ->
- {[],[],add_error(Line, illegal_expr, St1)};
- {_, St1} ->
- {[],[],St1}
- end;
pattern({record,Line,Name,Pfs}, Vt, Old, Bvt, St) ->
case dict:find(Name, St#lint.records) of
{ok,{_Line,Fields}} ->
@@ -1851,13 +1804,6 @@ gexpr({tuple,_Line,Es}, Vt, St) ->
gexpr({record_index,Line,Name,Field}, _Vt, St) ->
check_record(Line, Name, St,
fun (Dfs, St1) -> record_field(Field, Name, Dfs, St1) end );
-gexpr({record_field,Line,_,_}=M, _Vt, St0) ->
- case expand_package(M, St0) of
- {error, St1} ->
- {[],add_error(Line, illegal_expr, St1)};
- {_, St1} ->
- {[], St1}
- end;
gexpr({record_field,Line,Rec,Name,Field}, Vt, St0) ->
{Rvt,St1} = gexpr(Rec, Vt, St0),
{Fvt,St2} = check_record(Line, Name, St1,
@@ -1996,8 +1942,6 @@ is_gexpr({tuple,_L,Es}, RDs) -> is_gexpr_list(Es, RDs);
%% is_gexpr_list(Es, RDs);
is_gexpr({record_index,_L,_Name,Field}, RDs) ->
is_gexpr(Field, RDs);
-is_gexpr({record_field,_L,_,_}=M, _RDs) ->
- erl_parse:package_segments(M) =/= error;
is_gexpr({record_field,_L,Rec,_Name,Field}, RDs) ->
is_gexpr_list([Rec,Field], RDs);
is_gexpr({record,L,Name,Inits}, RDs) ->
@@ -2086,13 +2030,6 @@ expr({record,Line,Name,Inits}, Vt, St) ->
fun (Dfs, St1) ->
init_fields(Inits, Line, Name, Dfs, Vt, St1)
end);
-expr({record_field,Line,_,_}=M, _Vt, St0) ->
- case expand_package(M, St0) of
- {error, St1} ->
- {[],add_error(Line, illegal_expr, St1)};
- {_, St1} ->
- {[], St1}
- end;
expr({record_field,Line,Rec,Name,Field}, Vt, St0) ->
{Rvt,St1} = record_expr(Line, Rec, Vt, St0),
{Fvt,St2} = check_record(Line, Name, St1,
@@ -2163,20 +2100,14 @@ expr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]},
expr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0);
expr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,is_record}]},As}, Vt, St) ->
expr({call,L,{remote,Lt,{atom,Lm,erlang},{atom,Lf,is_record}},As}, Vt, St);
+expr({call,Line,{remote,_Lr,{atom,_Lm,M},{atom,Lf,F}},As}, Vt, St0) ->
+ St1 = keyword_warning(Lf, F, St0),
+ St2 = check_remote_function(Line, M, F, As, St1),
+ expr_list(As, Vt, St2);
expr({call,Line,{remote,_Lr,M,F},As}, Vt, St0) ->
- case expand_package(M, St0) of
- {error, _} ->
- expr_list([M,F|As], Vt, St0);
- {{atom,_La,M1}, St1} ->
- case F of
- {atom,Lf,F1} ->
- St2 = keyword_warning(Lf, F1, St1),
- St3 = check_remote_function(Line, M1, F1, As, St2),
- expr_list(As, Vt, St3);
- _ ->
- expr_list([F|As], Vt, St1)
- end
- end;
+ St1 = keyword_warning(Line, M, St0),
+ St2 = keyword_warning(Line, F, St1),
+ expr_list([M,F|As], Vt, St2);
expr({call,Line,{atom,La,F},As}, Vt, St0) ->
St1 = keyword_warning(La, F, St0),
{Asvt,St2} = expr_list(As, Vt, St1),
@@ -2232,13 +2163,6 @@ expr({call,Line,{atom,La,F},As}, Vt, St0) ->
end
end}
end;
-expr({call,Line,{record_field,_,_,_}=F,As}, Vt, St0) ->
- case expand_package(F, St0) of
- {error, _} ->
- expr_list([F|As], Vt, St0);
- {A, St1} ->
- expr({call,Line,A,As}, Vt, St1)
- end;
expr({call,Line,F,As}, Vt, St0) ->
St = warn_invalid_call(Line,F,St0),
expr_list([F|As], Vt, St); %They see the same variables
@@ -3618,6 +3542,10 @@ extract_sequence(4, [$t, $c | Fmt], Need) ->
extract_sequence(5, [$c|Fmt], Need);
extract_sequence(4, [$t, $s | Fmt], Need) ->
extract_sequence(5, [$s|Fmt], Need);
+extract_sequence(4, [$t, $p | Fmt], Need) ->
+ extract_sequence(5, [$p|Fmt], Need);
+extract_sequence(4, [$t, $P | Fmt], Need) ->
+ extract_sequence(5, [$P|Fmt], Need);
extract_sequence(4, [$t, C | _Fmt], _Need) ->
{error,"invalid control ~t" ++ [C]};
extract_sequence(4, Fmt, Need) ->
@@ -3654,49 +3582,6 @@ control_type($n, Need) -> Need;
control_type($i, Need) -> [term|Need];
control_type(_C, _Need) -> error.
-%% In syntax trees, module/package names are atoms or lists of atoms.
-
-package_to_string(A) when is_atom(A) -> atom_to_list(A);
-package_to_string(L) when is_list(L) -> packages:concat(L).
-
-expand_package({atom,L,A} = M, St0) ->
- St1 = keyword_warning(L, A, St0),
- case dict:find(A, St1#lint.mod_imports) of
- {ok, A1} ->
- {{atom,L,A1}, St1};
- error ->
- Name = atom_to_list(A),
- case packages:is_valid(Name) of
- true ->
- case packages:is_segmented(Name) of
- true ->
- {M, St1};
- false ->
- M1 = packages:concat(St1#lint.package,
- Name),
- {{atom,L,list_to_atom(M1)}, St1}
- end;
- false ->
- St2 = add_error(L, {bad_module_name, Name}, St1),
- {error, St2}
- end
- end;
-expand_package(M, St0) ->
- L = element(2, M),
- case erl_parse:package_segments(M) of
- error ->
- {error, St0};
- M1 ->
- Name = package_to_string(M1),
- case packages:is_valid(Name) of
- true ->
- {{atom,L,list_to_atom(Name)}, St0};
- false ->
- St1 = add_error(L, {bad_module_name, Name}, St0),
- {error, St1}
- end
- end.
-
%% Prebuild set of local functions (to override auto-import)
local_functions(Forms) ->
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 928c10f7f2..002abc11e8 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -26,7 +26,7 @@ attribute attr_val
function function_clauses function_clause
clause_args clause_guard clause_body
expr expr_100 expr_150 expr_160 expr_200 expr_300 expr_400 expr_500
-expr_600 expr_700 expr_800 expr_900
+expr_600 expr_700 expr_800
expr_max
list tail
list_comprehension lc_expr lc_exprs
@@ -253,15 +253,9 @@ expr_700 -> function_call : '$1'.
expr_700 -> record_expr : '$1'.
expr_700 -> expr_800 : '$1'.
-expr_800 -> expr_900 ':' expr_max :
+expr_800 -> expr_max ':' expr_max :
{remote,?line('$2'),'$1','$3'}.
-expr_800 -> expr_900 : '$1'.
-
-expr_900 -> '.' atom :
- {record_field,?line('$1'),{atom,?line('$1'),''},'$2'}.
-expr_900 -> expr_900 '.' atom :
- {record_field,?line('$2'),'$1','$3'}.
-expr_900 -> expr_max : '$1'.
+expr_800 -> expr_max : '$1'.
expr_max -> var : '$1'.
expr_max -> atomic : '$1'.
@@ -510,7 +504,7 @@ Erlang code.
-export([parse_form/1,parse_exprs/1,parse_term/1]).
-export([normalise/1,abstract/1,tokens/1,tokens/2]).
--export([abstract/2, package_segments/1]).
+-export([abstract/2]).
-export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]).
-export([set_line/2,get_attribute/2,get_attributes/1]).
@@ -679,20 +673,6 @@ build_attribute({atom,La,module}, Val) ->
{attribute,La,module,Module};
[{atom,_Lm,Module},ExpList] ->
{attribute,La,module,{Module,var_list(ExpList)}};
- [Name] ->
- case package_segments(Name) of
- error ->
- error_bad_decl(La, module);
- Module ->
- {attribute,La,module,Module}
- end;
- [Name,ExpList] ->
- case package_segments(Name) of
- error ->
- error_bad_decl(La, module);
- Module ->
- {attribute,La,module,{Module,var_list(ExpList)}}
- end;
_Other ->
error_bad_decl(La, module)
end;
@@ -704,22 +684,8 @@ build_attribute({atom,La,export}, Val) ->
end;
build_attribute({atom,La,import}, Val) ->
case Val of
- [Name] ->
- case package_segments(Name) of
- error ->
- error_bad_decl(La, import);
- Module ->
- {attribute,La,import,Module}
- end;
[{atom,_Lm,Mod},ImpList] ->
{attribute,La,import,{Mod,farity_list(ImpList)}};
- [Name, ImpList] ->
- case package_segments(Name) of
- error ->
- error_bad_decl(La, import);
- Module ->
- {attribute,La,import,{Module,farity_list(ImpList)}}
- end;
_Other -> error_bad_decl(La, import)
end;
build_attribute({atom,La,record}, Val) ->
@@ -820,18 +786,6 @@ term(Expr) ->
catch _:_R -> ret_err(?line(Expr), "bad attribute")
end.
-package_segments(Name) ->
- package_segments(Name, [], []).
-
-package_segments({record_field, _, F1, F2}, Fs, As) ->
- package_segments(F1, [F2 | Fs], As);
-package_segments({atom, _, A}, [F | Fs], As) ->
- package_segments(F, Fs, [A | As]);
-package_segments({atom, _, A}, [], As) ->
- lists:reverse([A | As]);
-package_segments(_, _, _) ->
- error.
-
%% build_function([Clause]) -> {function,Line,Name,Arity,[Clause]}
build_function(Cs) ->
@@ -900,12 +854,6 @@ normalise({cons,_,Head,Tail}) ->
[normalise(Head)|normalise(Tail)];
normalise({tuple,_,Args}) ->
list_to_tuple(normalise_list(Args));
-%% Atom dot-notation, as in 'foo.bar.baz'
-normalise({record_field,_,_,_}=A) ->
- case package_segments(A) of
- error -> erlang:error({badarg, A});
- As -> list_to_atom(packages:concat(As))
- end;
%% Special case for unary +/-.
normalise({op,_,'+',{char,_,I}}) -> I;
normalise({op,_,'+',{integer,_,I}}) -> I;
@@ -923,73 +871,77 @@ normalise_list([]) ->
-spec abstract(Data) -> AbsTerm when
Data :: term(),
AbsTerm :: abstract_expr().
-abstract(T) when is_integer(T) -> {integer,0,T};
-abstract(T) when is_float(T) -> {float,0,T};
-abstract(T) when is_atom(T) -> {atom,0,T};
-abstract([]) -> {nil,0};
-abstract(B) when is_bitstring(B) ->
- {bin, 0, [abstract_byte(Byte, 0) || Byte <- bitstring_to_list(B)]};
-abstract([C|T]) when is_integer(C), 0 =< C, C < 256 ->
- abstract_string(T, [C]);
-abstract([H|T]) ->
- {cons,0,abstract(H),abstract(T)};
-abstract(Tuple) when is_tuple(Tuple) ->
- {tuple,0,abstract_list(tuple_to_list(Tuple))}.
-
-abstract_string([C|T], String) when is_integer(C), 0 =< C, C < 256 ->
- abstract_string(T, [C|String]);
-abstract_string([], String) ->
- {string, 0, lists:reverse(String)};
-abstract_string(T, String) ->
- not_string(String, abstract(T)).
-
-not_string([C|T], Result) ->
- not_string(T, {cons, 0, {integer, 0, C}, Result});
-not_string([], Result) ->
+abstract(T) ->
+ abstract(T, 0, epp:default_encoding()).
+
+%%% abstract/2 takes line and encoding options
+-spec abstract(Data, Options) -> AbsTerm when
+ Data :: term(),
+ Options :: Line | [Option],
+ Option :: {line, Line} | {encoding, Encoding},
+ Encoding :: latin1 | unicode | utf8,
+ Line :: erl_scan:line(),
+ AbsTerm :: abstract_expr().
+
+abstract(T, Line) when is_integer(Line) ->
+ abstract(T, Line, epp:default_encoding());
+abstract(T, Options) when is_list(Options) ->
+ Line = proplists:get_value(line, Options, 0),
+ Encoding = proplists:get_value(encoding, Options,epp:default_encoding()),
+ abstract(T, Line, Encoding).
+
+-define(UNICODE(C),
+ (C >= 0 andalso C < 16#D800 orelse
+ C > 16#DFFF andalso C < 16#FFFE orelse
+ C > 16#FFFF andalso C =< 16#10FFFF)).
+
+abstract(T, L, _E) when is_integer(T) -> {integer,L,T};
+abstract(T, L, _E) when is_float(T) -> {float,L,T};
+abstract(T, L, _E) when is_atom(T) -> {atom,L,T};
+abstract([], L, _E) -> {nil,L};
+abstract(B, L, _E) when is_bitstring(B) ->
+ {bin, L, [abstract_byte(Byte, L) || Byte <- bitstring_to_list(B)]};
+abstract([C|T], L, unicode=E) when ?UNICODE(C) ->
+ abstract_unicode_string(T, [C], L, E);
+abstract([C|T], L, utf8=E) when ?UNICODE(C) ->
+ abstract_unicode_string(T, [C], L, E);
+abstract([C|T], L, latin1=E) when is_integer(C), 0 =< C, C < 256 ->
+ abstract_string(T, [C], L, E);
+abstract([H|T], L, E) ->
+ {cons,L,abstract(H, L, E),abstract(T, L, E)};
+abstract(Tuple, L, E) when is_tuple(Tuple) ->
+ {tuple,L,abstract_list(tuple_to_list(Tuple), L, E)}.
+
+abstract_string([C|T], String, L, E) when is_integer(C), 0 =< C, C < 256 ->
+ abstract_string(T, [C|String], L, E);
+abstract_string([], String, L, _E) ->
+ {string, L, lists:reverse(String)};
+abstract_string(T, String, L, E) ->
+ not_string(String, abstract(T, L, E), L, E).
+
+abstract_unicode_string([C|T], String, L, E) when ?UNICODE(C) ->
+ abstract_unicode_string(T, [C|String], L, E);
+abstract_unicode_string([], String, L, _E) ->
+ {string, L, lists:reverse(String)};
+abstract_unicode_string(T, String, L, E) ->
+ not_string(String, abstract(T, L, E), L, E).
+
+not_string([C|T], Result, L, E) ->
+ not_string(T, {cons, L, {integer, L, C}, Result}, L, E);
+not_string([], Result, _L, _E) ->
Result.
-abstract_list([H|T]) ->
- [abstract(H)|abstract_list(T)];
-abstract_list([]) ->
+abstract_list([H|T], L, E) ->
+ [abstract(H, L, E)|abstract_list(T, L, E)];
+abstract_list([], _L, _E) ->
[].
-abstract_byte(Byte, Line) when is_integer(Byte) ->
- {bin_element, Line, {integer, Line, Byte}, default, default};
-abstract_byte(Bits, Line) ->
+abstract_byte(Byte, L) when is_integer(Byte) ->
+ {bin_element, L, {integer, L, Byte}, default, default};
+abstract_byte(Bits, L) ->
Sz = bit_size(Bits),
<<Val:Sz>> = Bits,
- {bin_element, Line, {integer, Line, Val}, {integer, Line, Sz}, default}.
-
-%%% abstract/2 keeps the line number
-abstract(T, Line) when is_integer(T) -> {integer,Line,T};
-abstract(T, Line) when is_float(T) -> {float,Line,T};
-abstract(T, Line) when is_atom(T) -> {atom,Line,T};
-abstract([], Line) -> {nil,Line};
-abstract(B, Line) when is_bitstring(B) ->
- {bin, Line, [abstract_byte(Byte, Line) || Byte <- bitstring_to_list(B)]};
-abstract([C|T], Line) when is_integer(C), 0 =< C, C < 256 ->
- abstract_string(T, [C], Line);
-abstract([H|T], Line) ->
- {cons,Line,abstract(H, Line),abstract(T, Line)};
-abstract(Tuple, Line) when is_tuple(Tuple) ->
- {tuple,Line,abstract_list(tuple_to_list(Tuple), Line)}.
-
-abstract_string([C|T], String, Line) when is_integer(C), 0 =< C, C < 256 ->
- abstract_string(T, [C|String], Line);
-abstract_string([], String, Line) ->
- {string, Line, lists:reverse(String)};
-abstract_string(T, String, Line) ->
- not_string(String, abstract(T, Line), Line).
-
-not_string([C|T], Result, Line) ->
- not_string(T, {cons, Line, {integer, Line, C}, Result}, Line);
-not_string([], Result, _Line) ->
- Result.
-
-abstract_list([H|T], Line) ->
- [abstract(H, Line)|abstract_list(T, Line)];
-abstract_list([], _Line) ->
- [].
+ {bin_element, L, {integer, L, Val}, {integer, L, Sz}, default}.
%% Generate a list of tokens representing the abstract term.
@@ -1079,9 +1031,9 @@ preop_prec('#') -> {700,800}.
func_prec() -> {800,700}.
--spec max_prec() -> 1000.
+-spec max_prec() -> 900.
-max_prec() -> 1000.
+max_prec() -> 900.
%%% [Experimental]. The parser just copies the attributes of the
%%% scanner tokens to the abstract format. This design decision has
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 6b5aa951cf..0383ce6839 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -26,7 +26,7 @@
guard/1,guard/2,exprs/1,exprs/2,exprs/3,expr/1,expr/2,expr/3,expr/4]).
-import(lists, [append/1,foldr/3,mapfoldl/3,reverse/1,reverse/2]).
--import(io_lib, [write/1,format/2,write_char/1,write_string/1]).
+-import(io_lib, [write/1,format/2]).
-import(erl_parse, [inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]).
-define(MAXLINE, 72).
@@ -36,7 +36,15 @@
CurrentIndentation :: integer(),
CurrentPrecedence :: non_neg_integer(),
HookFunction :: hook_function()) ->
- io_lib:chars())).
+ io_lib:chars())).
+
+-type(option() :: {hook, hook_function()}
+ | {encoding, latin1 | unicode | utf8}).
+-type(options() :: hook_function() | [option()]).
+
+-record(pp, {string_fun, char_fun}).
+
+-record(options, {hook, encoding, opts}).
%%%
%%% Exported functions
@@ -48,12 +56,12 @@
form(Thing) ->
form(Thing, none).
--spec(form(Form, HookFunction) -> io_lib:chars() when
+-spec(form(Form, Options) -> io_lib:chars() when
Form :: erl_parse:abstract_form(),
- HookFunction :: hook_function()).
+ Options :: options()).
-form(Thing, Hook) ->
- frmt(lform(Thing, Hook)).
+form(Thing, Options) ->
+ frmt(lform(Thing, options(Options)), state(Options)).
-spec(attribute(Attribute) -> io_lib:chars() when
Attribute :: erl_parse:abstract_form()).
@@ -61,12 +69,12 @@ form(Thing, Hook) ->
attribute(Thing) ->
attribute(Thing, none).
--spec(attribute(Attribute, HookFunction) -> io_lib:chars() when
+-spec(attribute(Attribute, Options) -> io_lib:chars() when
Attribute :: erl_parse:abstract_form(),
- HookFunction :: hook_function()).
+ Options :: options()).
-attribute(Thing, Hook) ->
- frmt(lattribute(Thing, Hook)).
+attribute(Thing, Options) ->
+ frmt(lattribute(Thing, options(Options)), state(Options)).
-spec(function(Function) -> io_lib:chars() when
Function :: erl_parse:abstract_form()).
@@ -74,18 +82,18 @@ attribute(Thing, Hook) ->
function(F) ->
function(F, none).
--spec(function(Function, HookFunction) -> io_lib:chars() when
+-spec(function(Function, Options) -> io_lib:chars() when
Function :: erl_parse:abstract_form(),
- HookFunction :: hook_function()).
+ Options :: options()).
-function(F, Hook) ->
- frmt(lfunction(F, Hook)).
+function(F, Options) ->
+ frmt(lfunction(F, options(Options)), state(Options)).
rule(R) ->
rule(R, none).
-rule(R, Hook) ->
- frmt(lrule(R, Hook)).
+rule(R, Options) ->
+ frmt(lrule(R, options(Options)), state(Options)).
-spec(guard(Guard) -> io_lib:chars() when
Guard :: [erl_parse:abstract_expr()]).
@@ -93,12 +101,12 @@ rule(R, Hook) ->
guard(Gs) ->
guard(Gs, none).
--spec(guard(Guard, HookFunction) -> io_lib:chars() when
+-spec(guard(Guard, Options) -> io_lib:chars() when
Guard :: [erl_parse:abstract_expr()],
- HookFunction :: hook_function()).
+ Options :: options()).
-guard(Gs, Hook) ->
- frmt(lguard(Gs, Hook)).
+guard(Gs, Options) ->
+ frmt(lguard(Gs, options(Options)), state(Options)).
-spec(exprs(Expressions) -> io_lib:chars() when
Expressions :: [erl_parse:abstract_expr()]).
@@ -106,99 +114,129 @@ guard(Gs, Hook) ->
exprs(Es) ->
exprs(Es, 0, none).
--spec(exprs(Expressions, HookFunction) -> io_lib:chars() when
+-spec(exprs(Expressions, Options) -> io_lib:chars() when
Expressions :: [erl_parse:abstract_expr()],
- HookFunction :: hook_function()).
+ Options :: options()).
-exprs(Es, Hook) ->
- exprs(Es, 0, Hook).
+exprs(Es, Options) ->
+ exprs(Es, 0, Options).
--spec(exprs(Expressions, Indent, HookFunction) -> io_lib:chars() when
+-spec(exprs(Expressions, Indent, Options) -> io_lib:chars() when
Expressions :: [erl_parse:abstract_expr()],
Indent :: integer(),
- HookFunction :: hook_function()).
+ Options :: options()).
-exprs(Es, I, Hook) ->
- frmt({seq,[],[],[$,],lexprs(Es, Hook)}, I).
+exprs(Es, I, Options) ->
+ frmt({seq,[],[],[$,],lexprs(Es, options(Options))}, I, state(Options)).
-spec(expr(Expression) -> io_lib:chars() when
Expression :: erl_parse:abstract_expr()).
expr(E) ->
- frmt(lexpr(E, 0, none)).
+ frmt(lexpr(E, 0, options(none)), state(none)).
--spec(expr(Expression, HookFunction) -> io_lib:chars() when
+-spec(expr(Expression, Options) -> io_lib:chars() when
Expression :: erl_parse:abstract_expr(),
- HookFunction :: hook_function()).
+ Options :: options()).
-expr(E, Hook) ->
- frmt(lexpr(E, 0, Hook)).
+expr(E, Options) ->
+ frmt(lexpr(E, 0, options(Options)), state(Options)).
--spec(expr(Expression, Indent, HookFunction) -> io_lib:chars() when
+-spec(expr(Expression, Indent, Options) -> io_lib:chars() when
Expression :: erl_parse:abstract_expr(),
Indent :: integer(),
- HookFunction :: hook_function()).
+ Options :: options()).
-expr(E, I, Hook) ->
- frmt(lexpr(E, 0, Hook), I).
+expr(E, I, Options) ->
+ frmt(lexpr(E, 0, options(Options)), I, state(Options)).
--spec(expr(Expression, Indent, Precedence, HookFunction) -> io_lib:chars() when
+-spec(expr(Expression, Indent, Precedence, Options) -> io_lib:chars() when
Expression :: erl_parse:abstract_expr(),
Indent :: integer(),
Precedence :: non_neg_integer(),
- HookFunction :: hook_function()).
+ Options :: options()).
-expr(E, I, P, Hook) ->
- frmt(lexpr(E, P, Hook), I).
+expr(E, I, P, Options) ->
+ frmt(lexpr(E, P, options(Options)), I, state(Options)).
%%%
%%% Local functions
%%%
-lform({attribute,Line,Name,Arg}, Hook) ->
- lattribute({attribute,Line,Name,Arg}, Hook);
-lform({function,Line,Name,Arity,Clauses}, Hook) ->
- lfunction({function,Line,Name,Arity,Clauses}, Hook);
-lform({rule,Line,Name,Arity,Clauses}, Hook) ->
- lrule({rule,Line,Name,Arity,Clauses}, Hook);
+options(Options) when is_list(Options) ->
+ Hook = proplists:get_value(hook, Options, none),
+ Encoding = encoding(Options),
+ #options{hook = Hook, encoding = Encoding, opts = Options};
+options(Hook) ->
+ #options{hook = Hook, encoding = encoding([]), opts = Hook}.
+
+state(Options) when is_list(Options) ->
+ case encoding(Options) of
+ latin1 -> state();
+ unicode -> unicode_state()
+ end;
+state(_Hook) ->
+ state().
+
+state() ->
+ #pp{string_fun = fun io_lib:write_unicode_string_as_latin1/1,
+ char_fun = fun io_lib:write_unicode_char_as_latin1/1}.
+
+unicode_state() ->
+ #pp{string_fun = fun io_lib:write_unicode_string/1,
+ char_fun = fun io_lib:write_unicode_char/1}.
+
+encoding(Options) ->
+ case proplists:get_value(encoding, Options, epp:default_encoding()) of
+ latin1 -> latin1;
+ utf8 -> unicode;
+ unicode -> unicode
+ end.
+
+lform({attribute,Line,Name,Arg}, Opts) ->
+ lattribute({attribute,Line,Name,Arg}, Opts);
+lform({function,Line,Name,Arity,Clauses}, Opts) ->
+ lfunction({function,Line,Name,Arity,Clauses}, Opts);
+lform({rule,Line,Name,Arity,Clauses}, Opts) ->
+ lrule({rule,Line,Name,Arity,Clauses}, Opts);
%% These are specials to make it easier for the compiler.
-lform({error,E}, _Hook) ->
+lform({error,E}, _Opts) ->
leaf(format("~p\n", [{error,E}]));
-lform({warning,W}, _Hook) ->
+lform({warning,W}, _Opts) ->
leaf(format("~p\n", [{warning,W}]));
-lform({eof,_Line}, _Hook) ->
+lform({eof,_Line}, _Opts) ->
$\n.
-lattribute({attribute,_Line,type,Type}, Hook) ->
- [typeattr(type, Type, Hook),leaf(".\n")];
-lattribute({attribute,_Line,opaque,Type}, Hook) ->
- [typeattr(opaque, Type, Hook),leaf(".\n")];
-lattribute({attribute,_Line,spec,Arg}, _Hook) ->
+lattribute({attribute,_Line,type,Type}, Opts) ->
+ [typeattr(type, Type, Opts),leaf(".\n")];
+lattribute({attribute,_Line,opaque,Type}, Opts) ->
+ [typeattr(opaque, Type, Opts),leaf(".\n")];
+lattribute({attribute,_Line,spec,Arg}, _Opts) ->
[specattr(Arg),leaf(".\n")];
-lattribute({attribute,_Line,Name,Arg}, Hook) ->
- [lattribute(Name, Arg, Hook),leaf(".\n")].
+lattribute({attribute,_Line,Name,Arg}, Opts) ->
+ [lattribute(Name, Arg, Opts),leaf(".\n")].
-lattribute(module, {M,Vs}, _Hook) ->
+lattribute(module, {M,Vs}, _Opts) ->
attr("module",[{var,0,pname(M)},
foldr(fun(V, C) -> {cons,0,{var,0,V},C}
end, {nil,0}, Vs)]);
-lattribute(module, M, _Hook) ->
+lattribute(module, M, _Opts) ->
attr("module", [{var,0,pname(M)}]);
-lattribute(export, Falist, _Hook) ->
+lattribute(export, Falist, _Opts) ->
call({var,0,"-export"}, [falist(Falist)], 0, none);
-lattribute(import, Name, _Hook) when is_list(Name) ->
+lattribute(import, Name, _Opts) when is_list(Name) ->
attr("import", [{var,0,pname(Name)}]);
-lattribute(import, {From,Falist}, _Hook) ->
+lattribute(import, {From,Falist}, _Opts) ->
attr("import",[{var,0,pname(From)},falist(Falist)]);
-lattribute(file, {Name,Line}, _Hook) ->
+lattribute(file, {Name,Line}, _Opts) ->
attr("file", [{var,0,format("~p", [Name])},{integer,0,Line}]);
-lattribute(record, {Name,Is}, Hook) ->
+lattribute(record, {Name,Is}, Opts) ->
Nl = leaf(format("-record(~w,", [Name])),
- [{first,Nl,record_fields(Is, Hook)},$)];
-lattribute(Name, Arg, _Hook) ->
- attr(write(Name), [erl_parse:abstract(Arg)]).
+ [{first,Nl,record_fields(Is, Opts)},$)];
+lattribute(Name, Arg, #options{encoding = Encoding}) ->
+ attr(write(Name), [erl_parse:abstract(Arg, [{encoding,Encoding}])]).
-typeattr(Tag, {TypeName,Type,Args}, _Hook) ->
+typeattr(Tag, {TypeName,Type,Args}, _Opts) ->
{first,leaf("-"++atom_to_list(Tag)++" "),
typed(call({atom,0,TypeName}, Args, 0, none), Type)}.
@@ -293,7 +331,7 @@ guard_type(Before, Gs) ->
Gl = {list,[{step,'when',expr_list(Gs, [$,], fun constraint/2, none)}]},
{list,[{step,Before,Gl}]}.
-constraint({type,_Line,constraint,[Tag,As]}, _Hook) ->
+constraint({type,_Line,constraint,[Tag,As]}, _Opts) ->
simple_type(Tag, As).
fun_type(Before, {type,_,'fun',[FType,Ret]}) ->
@@ -333,231 +371,232 @@ falist([]) ->
falist([{Name,Arity}|Falist]) ->
{cons,0,{var,0,format("~w/~w", [Name,Arity])},falist(Falist)}.
-lfunction({function,_Line,Name,_Arity,Cs}, Hook) ->
- Cll = nl_clauses(fun (C, H) -> func_clause(Name, C, H) end, $;, Hook, Cs),
+lfunction({function,_Line,Name,_Arity,Cs}, Opts) ->
+ Cll = nl_clauses(fun (C, H) -> func_clause(Name, C, H) end, $;, Opts, Cs),
[Cll,leaf(".\n")].
-func_clause(Name, {clause,Line,Head,Guard,Body}, Hook) ->
- Hl = call({atom,Line,Name}, Head, 0, Hook),
- Gl = guard_when(Hl, Guard, Hook),
- Bl = body(Body, Hook),
+func_clause(Name, {clause,Line,Head,Guard,Body}, Opts) ->
+ Hl = call({atom,Line,Name}, Head, 0, Opts),
+ Gl = guard_when(Hl, Guard, Opts),
+ Bl = body(Body, Opts),
{step,Gl,Bl}.
-lrule({rule,_Line,Name,_Arity,Cs}, Hook) ->
- Cll = nl_clauses(fun (C, H) -> rule_clause(Name, C, H) end, $;, Hook, Cs),
+lrule({rule,_Line,Name,_Arity,Cs}, Opts) ->
+ Cll = nl_clauses(fun (C, H) -> rule_clause(Name, C, H) end, $;, Opts, Cs),
[Cll,leaf(".\n")].
-rule_clause(Name, {clause,Line,Head,Guard,Body}, Hook) ->
- Hl = call({atom,Line,Name}, Head, 0, Hook),
- Gl = guard_when(Hl, Guard, Hook, leaf(" :-")),
- Bl = rule_body(Body, Hook),
+rule_clause(Name, {clause,Line,Head,Guard,Body}, Opts) ->
+ Hl = call({atom,Line,Name}, Head, 0, Opts),
+ Gl = guard_when(Hl, Guard, Opts, leaf(" :-")),
+ Bl = rule_body(Body, Opts),
{step,Gl,Bl}.
-rule_body(Es, Hook) ->
- lc_quals(Es, Hook).
+rule_body(Es, Opts) ->
+ lc_quals(Es, Opts).
-guard_when(Before, Guard, Hook) ->
- guard_when(Before, Guard, Hook, ' ->').
+guard_when(Before, Guard, Opts) ->
+ guard_when(Before, Guard, Opts, ' ->').
-guard_when(Before, Guard, Hook, After) ->
- Gl = lguard(Guard, Hook),
+guard_when(Before, Guard, Opts, After) ->
+ Gl = lguard(Guard, Opts),
[{list,[{step,Before,Gl}]},After].
-lguard([E|Es], Hook) when is_list(E) ->
- {list,[{step,'when',expr_list([E|Es], [$;], fun guard0/2, Hook)}]};
-lguard([E|Es], Hook) -> % before R6
- lguard([[E|Es]], Hook);
+lguard([E|Es], Opts) when is_list(E) ->
+ {list,[{step,'when',expr_list([E|Es], [$;], fun guard0/2, Opts)}]};
+lguard([E|Es], Opts) -> % before R6
+ lguard([[E|Es]], Opts);
lguard([], _) ->
[].
-guard0(Es, Hook) ->
- expr_list(Es, [$,], fun lexpr/2, Hook).
+guard0(Es, Opts) ->
+ expr_list(Es, [$,], fun lexpr/2, Opts).
-%% body(Before, Es, Hook) -> [Char].
+%% body(Before, Es, Opts) -> [Char].
-body([E], Hook) ->
- lexpr(E, Hook);
-body(Es, Hook) ->
- {prefer_nl,[$,],lexprs(Es, Hook)}.
+body([E], Opts) ->
+ lexpr(E, Opts);
+body(Es, Opts) ->
+ {prefer_nl,[$,],lexprs(Es, Opts)}.
-lexpr(E, Hook) ->
- lexpr(E, 0, Hook).
+lexpr(E, Opts) ->
+ lexpr(E, 0, Opts).
lexpr({var,_,V}, _, _) when is_integer(V) -> %Special hack for Robert
leaf(format("_~w", [V]));
lexpr({var,_,V}, _, _) -> leaf(format("~s", [V]));
-lexpr({char,_,C}, _, _) -> leaf(write_char(C));
+lexpr({char,_,C}, _, _) -> {char,C};
lexpr({integer,_,N}, _, _) -> leaf(write(N));
lexpr({float,_,F}, _, _) -> leaf(write(F));
lexpr({atom,_,A}, _, _) -> leaf(write(A));
lexpr({string,_,S}, _, _) -> {string,S};
lexpr({nil,_}, _, _) -> '[]';
-lexpr({cons,_,H,T}, _, Hook) ->
- list(T, [H], Hook);
-lexpr({lc,_,E,Qs}, _Prec, Hook) ->
- Lcl = {list,[{step,[lexpr(E, Hook),leaf(" ||")],lc_quals(Qs, Hook)}]},
+lexpr({cons,_,H,T}, _, Opts) ->
+ list(T, [H], Opts);
+lexpr({lc,_,E,Qs}, _Prec, Opts) ->
+ Lcl = {list,[{step,[lexpr(E, Opts),leaf(" ||")],lc_quals(Qs, Opts)}]},
{list,[{seq,$[,[],[[]],[{force_nl,leaf(" "),[Lcl]}]},$]]};
%% {list,[{step,$[,Lcl},$]]};
-lexpr({bc,_,E,Qs}, _Prec, Hook) ->
- Lcl = {list,[{step,[lexpr(E, Hook),leaf(" ||")],lc_quals(Qs, Hook)}]},
+lexpr({bc,_,E,Qs}, _Prec, Opts) ->
+ Lcl = {list,[{step,[lexpr(E, Opts),leaf(" ||")],lc_quals(Qs, Opts)}]},
{list,[{seq,'<<',[],[[]],[{force_nl,leaf(" "),[Lcl]}]},'>>']};
%% {list,[{step,'<<',Lcl},'>>']};
-lexpr({tuple,_,Elts}, _, Hook) ->
- tuple(Elts, Hook);
-%%lexpr({struct,_,Tag,Elts}, _, Hook) ->
-%% {first,format("~w", [Tag]),tuple(Elts, Hook)};
-lexpr({record_index, _, Name, F}, Prec, Hook) ->
+lexpr({tuple,_,Elts}, _, Opts) ->
+ tuple(Elts, Opts);
+%%lexpr({struct,_,Tag,Elts}, _, Opts) ->
+%% {first,format("~w", [Tag]),tuple(Elts, Opts)};
+lexpr({record_index, _, Name, F}, Prec, Opts) ->
{P,R} = preop_prec('#'),
Nl = record_name(Name),
- El = [Nl,$.,lexpr(F, R, Hook)],
+ El = [Nl,$.,lexpr(F, R, Opts)],
maybe_paren(P, Prec, El);
-lexpr({record, _, Name, Fs}, Prec, Hook) ->
+lexpr({record, _, Name, Fs}, Prec, Opts) ->
{P,_R} = preop_prec('#'),
Nl = record_name(Name),
- El = {first,Nl,record_fields(Fs, Hook)},
+ El = {first,Nl,record_fields(Fs, Opts)},
maybe_paren(P, Prec, El);
-lexpr({record_field, _, Rec, Name, F}, Prec, Hook) ->
+lexpr({record_field, _, Rec, Name, F}, Prec, Opts) ->
{L,P,R} = inop_prec('#'),
- Rl = lexpr(Rec, L, Hook),
+ Rl = lexpr(Rec, L, Opts),
Nl = leaf(format("#~w.", [Name])),
- El = [Rl,Nl,lexpr(F, R, Hook)],
+ El = [Rl,Nl,lexpr(F, R, Opts)],
maybe_paren(P, Prec, El);
-lexpr({record, _, Rec, Name, Fs}, Prec, Hook) ->
+lexpr({record, _, Rec, Name, Fs}, Prec, Opts) ->
{L,P,_R} = inop_prec('#'),
- Rl = lexpr(Rec, L, Hook),
+ Rl = lexpr(Rec, L, Opts),
Nl = record_name(Name),
- El = {first,[Rl,Nl],record_fields(Fs, Hook)},
+ El = {first,[Rl,Nl],record_fields(Fs, Opts)},
maybe_paren(P, Prec, El);
-lexpr({record_field, _, {atom,_,''}, F}, Prec, Hook) ->
+lexpr({record_field, _, {atom,_,''}, F}, Prec, Opts) ->
{_L,P,R} = inop_prec('.'),
- El = [$.,lexpr(F, R, Hook)],
+ El = [$.,lexpr(F, R, Opts)],
maybe_paren(P, Prec, El);
-lexpr({record_field, _, Rec, F}, Prec, Hook) ->
+lexpr({record_field, _, Rec, F}, Prec, Opts) ->
{L,P,R} = inop_prec('.'),
- El = [lexpr(Rec, L, Hook),$.,lexpr(F, R, Hook)],
+ El = [lexpr(Rec, L, Opts),$.,lexpr(F, R, Opts)],
maybe_paren(P, Prec, El);
-lexpr({block,_,Es}, _, Hook) ->
- {list,[{step,'begin',body(Es, Hook)},'end']};
-lexpr({'if',_,Cs}, _, Hook) ->
- {list,[{step,'if',if_clauses(Cs, Hook)},'end']};
-lexpr({'case',_,Expr,Cs}, _, Hook) ->
- {list,[{step,{list,[{step,'case',lexpr(Expr, Hook)},'of']},
- cr_clauses(Cs, Hook)},
+lexpr({block,_,Es}, _, Opts) ->
+ {list,[{step,'begin',body(Es, Opts)},'end']};
+lexpr({'if',_,Cs}, _, Opts) ->
+ {list,[{step,'if',if_clauses(Cs, Opts)},'end']};
+lexpr({'case',_,Expr,Cs}, _, Opts) ->
+ {list,[{step,{list,[{step,'case',lexpr(Expr, Opts)},'of']},
+ cr_clauses(Cs, Opts)},
'end']};
-lexpr({'cond',_,Cs}, _, Hook) ->
- {list,[{step,leaf("cond"),cond_clauses(Cs, Hook)},'end']};
-lexpr({'receive',_,Cs}, _, Hook) ->
- {list,[{step,'receive',cr_clauses(Cs, Hook)},'end']};
-lexpr({'receive',_,Cs,To,ToOpt}, _, Hook) ->
- Al = {list,[{step,[lexpr(To, Hook),' ->'],body(ToOpt, Hook)}]},
- {list,[{step,'receive',cr_clauses(Cs, Hook)},
+lexpr({'cond',_,Cs}, _, Opts) ->
+ {list,[{step,leaf("cond"),cond_clauses(Cs, Opts)},'end']};
+lexpr({'receive',_,Cs}, _, Opts) ->
+ {list,[{step,'receive',cr_clauses(Cs, Opts)},'end']};
+lexpr({'receive',_,Cs,To,ToOpt}, _, Opts) ->
+ Al = {list,[{step,[lexpr(To, Opts),' ->'],body(ToOpt, Opts)}]},
+ {list,[{step,'receive',cr_clauses(Cs, Opts)},
{step,'after',Al},
'end']};
-lexpr({'fun',_,{function,F,A}}, _Prec, _Hook) ->
+lexpr({'fun',_,{function,F,A}}, _Prec, _Opts) ->
leaf(format("fun ~w/~w", [F,A]));
-lexpr({'fun',_,{function,F,A},Extra}, _Prec, _Hook) ->
+lexpr({'fun',_,{function,F,A},Extra}, _Prec, _Opts) ->
{force_nl,fun_info(Extra),leaf(format("fun ~w/~w", [F,A]))};
-lexpr({'fun',_,{function,M,F,A}}, _Prec, _Hook)
+lexpr({'fun',_,{function,M,F,A}}, _Prec, _Opts)
when is_atom(M), is_atom(F), is_integer(A) ->
%% For backward compatibility with pre-R15 abstract format.
leaf(format("fun ~w:~w/~w", [M,F,A]));
-lexpr({'fun',_,{function,M,F,A}}, _Prec, Hook) ->
+lexpr({'fun',_,{function,M,F,A}}, _Prec, Opts) ->
%% New format in R15.
- NameItem = lexpr(M, Hook),
- CallItem = lexpr(F, Hook),
- ArityItem = lexpr(A, Hook),
+ NameItem = lexpr(M, Opts),
+ CallItem = lexpr(F, Opts),
+ ArityItem = lexpr(A, Opts),
["fun ",NameItem,$:,CallItem,$/,ArityItem];
-lexpr({'fun',_,{clauses,Cs}}, _Prec, Hook) ->
- {list,[{first,'fun',fun_clauses(Cs, Hook)},'end']};
-lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Hook) ->
+lexpr({'fun',_,{clauses,Cs}}, _Prec, Opts) ->
+ {list,[{first,'fun',fun_clauses(Cs, Opts)},'end']};
+lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Opts) ->
{force_nl,fun_info(Extra),
- {list,[{first,'fun',fun_clauses(Cs, Hook)},'end']}};
-lexpr({'query',_,Lc}, _Prec, Hook) ->
- {list,[{step,leaf("query"),lexpr(Lc, 0, Hook)},'end']};
-lexpr({call,_,{remote,_,{atom,_,M},{atom,_,F}=N}=Name,Args}, Prec, Hook) ->
+ {list,[{first,'fun',fun_clauses(Cs, Opts)},'end']}};
+lexpr({'query',_,Lc}, _Prec, Opts) ->
+ {list,[{step,leaf("query"),lexpr(Lc, 0, Opts)},'end']};
+lexpr({call,_,{remote,_,{atom,_,M},{atom,_,F}=N}=Name,Args}, Prec, Opts) ->
case erl_internal:bif(M, F, length(Args)) of
true ->
- call(N, Args, Prec, Hook);
+ call(N, Args, Prec, Opts);
false ->
- call(Name, Args, Prec, Hook)
+ call(Name, Args, Prec, Opts)
end;
-lexpr({call,_,Name,Args}, Prec, Hook) ->
- call(Name, Args, Prec, Hook);
-lexpr({'try',_,Es,Scs,Ccs,As}, _, Hook) ->
+lexpr({call,_,Name,Args}, Prec, Opts) ->
+ call(Name, Args, Prec, Opts);
+lexpr({'try',_,Es,Scs,Ccs,As}, _, Opts) ->
{list,[if
Scs =:= [] ->
- {step,'try',body(Es, Hook)};
+ {step,'try',body(Es, Opts)};
true ->
- {step,{list,[{step,'try',body(Es, Hook)},'of']},
- cr_clauses(Scs, Hook)}
+ {step,{list,[{step,'try',body(Es, Opts)},'of']},
+ cr_clauses(Scs, Opts)}
end,
if
Ccs =:= [] ->
[];
true ->
- {step,'catch',try_clauses(Ccs, Hook)}
+ {step,'catch',try_clauses(Ccs, Opts)}
end,
if
As =:= [] ->
[];
true ->
- {step,'after',body(As, Hook)}
+ {step,'after',body(As, Opts)}
end,
'end']};
-lexpr({'catch',_,Expr}, Prec, Hook) ->
+lexpr({'catch',_,Expr}, Prec, Opts) ->
{P,R} = preop_prec('catch'),
- El = {list,[{step,'catch',lexpr(Expr, R, Hook)}]},
+ El = {list,[{step,'catch',lexpr(Expr, R, Opts)}]},
maybe_paren(P, Prec, El);
-lexpr({match,_,Lhs,Rhs}, Prec, Hook) ->
+lexpr({match,_,Lhs,Rhs}, Prec, Opts) ->
{L,P,R} = inop_prec('='),
- Pl = lexpr(Lhs, L, Hook),
- Rl = lexpr(Rhs, R, Hook),
+ 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, Hook) ->
+lexpr({op,_,Op,Arg}, Prec, Opts) ->
{P,R} = preop_prec(Op),
Ol = leaf(format("~s ", [Op])),
- El = [Ol,lexpr(Arg, R, Hook)],
+ El = [Ol,lexpr(Arg, R, Opts)],
maybe_paren(P, Prec, El);
-lexpr({op,_,Op,Larg,Rarg}, Prec, Hook) when Op =:= 'orelse';
+lexpr({op,_,Op,Larg,Rarg}, Prec, Opts) when Op =:= 'orelse';
Op =:= 'andalso' ->
%% Breaks lines since R12B.
{L,P,R} = inop_prec(Op),
- Ll = lexpr(Larg, L, Hook),
+ Ll = lexpr(Larg, L, Opts),
Ol = leaf(format("~s", [Op])),
- Lr = lexpr(Rarg, R, Hook),
+ Lr = lexpr(Rarg, R, Opts),
El = {prefer_nl,[[]],[Ll,Ol,Lr]},
maybe_paren(P, Prec, El);
-lexpr({op,_,Op,Larg,Rarg}, Prec, Hook) ->
+lexpr({op,_,Op,Larg,Rarg}, Prec, Opts) ->
{L,P,R} = inop_prec(Op),
- Ll = lexpr(Larg, L, Hook),
+ Ll = lexpr(Larg, L, Opts),
Ol = leaf(format("~s", [Op])),
- Lr = lexpr(Rarg, R, Hook),
+ Lr = lexpr(Rarg, R, Opts),
El = {list,[Ll,Ol,Lr]},
maybe_paren(P, Prec, El);
%% Special expressions which are not really legal everywhere.
-lexpr({remote,_,M,F}, Prec, Hook) ->
+lexpr({remote,_,M,F}, Prec, Opts) ->
{L,P,R} = inop_prec(':'),
- NameItem = lexpr(M, L, Hook),
- CallItem = lexpr(F, R, Hook),
+ NameItem = lexpr(M, L, Opts),
+ CallItem = lexpr(F, R, Opts),
maybe_paren(P, Prec, [NameItem,$:,CallItem]);
%% BIT SYNTAX:
-lexpr({bin,_,Fs}, _, Hook) ->
- bit_grp(Fs, Hook);
+lexpr({bin,_,Fs}, _, Opts) ->
+ bit_grp(Fs, Opts);
%% Special case for straight values.
lexpr({value,_,Val}, _,_) ->
leaf(write(Val));
%% Now do the hook.
-lexpr(Other, _Precedence, none) ->
+lexpr(Other, _Precedence, #options{hook = none}) ->
leaf(format("INVALID-FORM:~w:",[Other]));
-lexpr(HookExpr, Precedence, {Mod,Func,Eas}) when Mod =/= 'fun' ->
+lexpr(HookExpr, Precedence, #options{hook = {Mod,Func,Eas}})
+ when Mod =/= 'fun' ->
{ehook,HookExpr,Precedence,{Mod,Func,Eas}};
-lexpr(HookExpr, Precedence, Func) ->
- {hook,HookExpr,Precedence,Func}.
+lexpr(HookExpr, Precedence, #options{hook = Func, opts = Options}) ->
+ {hook,HookExpr,Precedence,Func,Options}.
-call(Name, Args, Prec, Hook) ->
+call(Name, Args, Prec, Opts) ->
{F,P} = func_prec(),
- Item = {first,lexpr(Name, F, Hook),args(Args, Hook)},
+ Item = {first,lexpr(Name, F, Opts),args(Args, Opts)},
maybe_paren(P, Prec, Item).
fun_info(Extra) ->
@@ -565,32 +604,18 @@ fun_info(Extra) ->
%% BITS:
-bit_grp(Fs, Hook) ->
- append([['<<'],
- [try
- true = Fs =/= [],
- S = bin_string(Fs),
- true = io_lib:printable_list(S),
- {string,S}
- catch _:_ ->
- bit_elems(Fs, Hook)
- end],
- ['>>']]).
-
-bin_string([]) ->
- [];
-bin_string([{bin_element,_,{char,_,C},_,_}|Bin]) ->
- [C | bin_string(Bin)].
+bit_grp(Fs, Opts) ->
+ append([['<<'], [bit_elems(Fs, Opts)], ['>>']]).
-bit_elems(Es, Hook) ->
- expr_list(Es, $,, fun bit_elem/2, Hook).
+bit_elems(Es, Opts) ->
+ expr_list(Es, $,, fun bit_elem/2, Opts).
-bit_elem({bin_element,_,Expr,Sz,Types}, Hook) ->
+bit_elem({bin_element,_,Expr,Sz,Types}, Opts) ->
P = max_prec(),
- VChars = lexpr(Expr, P, Hook),
+ VChars = lexpr(Expr, P, Opts),
SChars = if
Sz =/= default ->
- [VChars,$:,lexpr(Sz, P, Hook)];
+ [VChars,$:,lexpr(Sz, P, Opts)];
true ->
VChars
end,
@@ -618,157 +643,157 @@ bit_elem_type(T) ->
record_name(Name) ->
leaf(format("#~w", [Name])).
-record_fields(Fs, Hook) ->
- tuple(Fs, fun record_field/2, Hook).
+record_fields(Fs, Opts) ->
+ tuple(Fs, fun record_field/2, Opts).
-record_field({record_field,_,F,Val}, Hook) ->
+record_field({record_field,_,F,Val}, Opts) ->
{L,_P,R} = inop_prec('='),
- Fl = lexpr(F, L, Hook),
- Vl = lexpr(Val, R, Hook),
+ Fl = lexpr(F, L, Opts),
+ Vl = lexpr(Val, R, Opts),
{list,[{cstep,[Fl,' ='],Vl}]};
-record_field({typed_record_field,{record_field,_,F,Val},Type}, Hook) ->
+record_field({typed_record_field,{record_field,_,F,Val},Type}, Opts) ->
{L,_P,R} = inop_prec('='),
- Fl = lexpr(F, L, Hook),
- Vl = typed(lexpr(Val, R, Hook), Type),
+ Fl = lexpr(F, L, Opts),
+ Vl = typed(lexpr(Val, R, Opts), Type),
{list,[{cstep,[Fl,' ='],Vl}]};
-record_field({typed_record_field,Field,Type}, Hook) ->
- typed(record_field(Field, Hook), Type);
-record_field({record_field,_,F}, Hook) ->
- lexpr(F, 0, Hook).
-
-list({cons,_,H,T}, Es, Hook) ->
- list(T, [H|Es], Hook);
-list({nil,_}, Es, Hook) ->
- proper_list(reverse(Es), Hook);
-list(Other, Es, Hook) ->
- improper_list(reverse(Es, [Other]), Hook).
-
-%% if_clauses(Clauses, Hook) -> [Char].
+record_field({typed_record_field,Field,Type}, Opts) ->
+ typed(record_field(Field, Opts), Type);
+record_field({record_field,_,F}, Opts) ->
+ lexpr(F, 0, Opts).
+
+list({cons,_,H,T}, Es, Opts) ->
+ list(T, [H|Es], Opts);
+list({nil,_}, Es, Opts) ->
+ proper_list(reverse(Es), Opts);
+list(Other, Es, Opts) ->
+ improper_list(reverse(Es, [Other]), Opts).
+
+%% if_clauses(Clauses, Opts) -> [Char].
%% Print 'if' clauses.
-if_clauses(Cs, Hook) ->
- clauses(fun if_clause/2, Hook, Cs).
+if_clauses(Cs, Opts) ->
+ clauses(fun if_clause/2, Opts, Cs).
-if_clause({clause,_,[],G,B}, Hook) ->
- Gl = [guard_no_when(G, Hook),' ->'],
- {step,Gl,body(B, Hook)}.
+if_clause({clause,_,[],G,B}, Opts) ->
+ Gl = [guard_no_when(G, Opts),' ->'],
+ {step,Gl,body(B, Opts)}.
-guard_no_when([E|Es], Hook) when is_list(E) ->
- expr_list([E|Es], $;, fun guard0/2, Hook);
-guard_no_when([E|Es], Hook) -> % before R6
- guard_no_when([[E|Es]], Hook);
+guard_no_when([E|Es], Opts) when is_list(E) ->
+ expr_list([E|Es], $;, fun guard0/2, Opts);
+guard_no_when([E|Es], Opts) -> % before R6
+ guard_no_when([[E|Es]], Opts);
guard_no_when([], _) -> % cannot happen
leaf("true").
-%% cr_clauses(Clauses, Hook) -> [Char].
+%% cr_clauses(Clauses, Opts) -> [Char].
%% Print 'case'/'receive' clauses.
-cr_clauses(Cs, Hook) ->
- clauses(fun cr_clause/2, Hook, Cs).
+cr_clauses(Cs, Opts) ->
+ clauses(fun cr_clause/2, Opts, Cs).
-cr_clause({clause,_,[T],G,B}, Hook) ->
- El = lexpr(T, 0, Hook),
- Gl = guard_when(El, G, Hook),
- Bl = body(B, Hook),
+cr_clause({clause,_,[T],G,B}, Opts) ->
+ El = lexpr(T, 0, Opts),
+ Gl = guard_when(El, G, Opts),
+ Bl = body(B, Opts),
{step,Gl,Bl}.
-%% try_clauses(Clauses, Hook) -> [Char].
+%% try_clauses(Clauses, Opts) -> [Char].
%% Print 'try' clauses.
-try_clauses(Cs, Hook) ->
- clauses(fun try_clause/2, Hook, Cs).
+try_clauses(Cs, Opts) ->
+ clauses(fun try_clause/2, Opts, Cs).
-try_clause({clause,_,[{tuple,_,[{atom,_,throw},V,S]}],G,B}, Hook) ->
- El = lexpr(V, 0, Hook),
- Sl = stack_backtrace(S, [El], Hook),
- Gl = guard_when(Sl, G, Hook),
- Bl = body(B, Hook),
+try_clause({clause,_,[{tuple,_,[{atom,_,throw},V,S]}],G,B}, Opts) ->
+ El = lexpr(V, 0, Opts),
+ Sl = stack_backtrace(S, [El], Opts),
+ Gl = guard_when(Sl, G, Opts),
+ Bl = body(B, Opts),
{step,Gl,Bl};
-try_clause({clause,_,[{tuple,_,[C,V,S]}],G,B}, Hook) ->
- Cs = lexpr(C, 0, Hook),
- El = lexpr(V, 0, Hook),
+try_clause({clause,_,[{tuple,_,[C,V,S]}],G,B}, Opts) ->
+ Cs = lexpr(C, 0, Opts),
+ El = lexpr(V, 0, Opts),
CsEl = [Cs,$:,El],
- Sl = stack_backtrace(S, CsEl, Hook),
- Gl = guard_when(Sl, G, Hook),
- Bl = body(B, Hook),
+ Sl = stack_backtrace(S, CsEl, Opts),
+ Gl = guard_when(Sl, G, Opts),
+ Bl = body(B, Opts),
{step,Gl,Bl}.
-stack_backtrace({var,_,'_'}, El, _Hook) ->
+stack_backtrace({var,_,'_'}, El, _Opts) ->
El;
-stack_backtrace(S, El, Hook) ->
- El++[$:,lexpr(S, 0, Hook)].
+stack_backtrace(S, El, Opts) ->
+ El++[$:,lexpr(S, 0, Opts)].
-%% fun_clauses(Clauses, Hook) -> [Char].
+%% fun_clauses(Clauses, Opts) -> [Char].
%% Print 'fun' clauses.
-fun_clauses(Cs, Hook) ->
- nl_clauses(fun fun_clause/2, [$;], Hook, Cs).
+fun_clauses(Cs, Opts) ->
+ nl_clauses(fun fun_clause/2, [$;], Opts, Cs).
-fun_clause({clause,_,A,G,B}, Hook) ->
- El = args(A, Hook),
- Gl = guard_when(El, G, Hook),
- Bl = body(B, Hook),
+fun_clause({clause,_,A,G,B}, Opts) ->
+ El = args(A, Opts),
+ Gl = guard_when(El, G, Opts),
+ Bl = body(B, Opts),
{step,Gl,Bl}.
-%% cond_clauses(Clauses, Hook) -> [Char].
+%% cond_clauses(Clauses, Opts) -> [Char].
%% Print 'cond' clauses.
-cond_clauses(Cs, Hook) ->
- clauses(fun cond_clause/2, Hook, Cs).
+cond_clauses(Cs, Opts) ->
+ clauses(fun cond_clause/2, Opts, Cs).
-cond_clause({clause,_,[],[[E]],B}, Hook) ->
- {step,[lexpr(E, Hook),' ->'],body(B, Hook)}.
+cond_clause({clause,_,[],[[E]],B}, Opts) ->
+ {step,[lexpr(E, Opts),' ->'],body(B, Opts)}.
-%% nl_clauses(Type, Hook, Clauses) -> [Char].
+%% nl_clauses(Type, Opts, Clauses) -> [Char].
%% Generic clause printing function (always breaks lines).
-nl_clauses(Type, Sep, Hook, Cs) ->
- {prefer_nl,Sep,lexprs(Cs, Type, Hook)}.
+nl_clauses(Type, Sep, Opts, Cs) ->
+ {prefer_nl,Sep,lexprs(Cs, Type, Opts)}.
-%% clauses(Type, Hook, Clauses) -> [Char].
+%% clauses(Type, Opts, Clauses) -> [Char].
%% Generic clause printing function (breaks lines since R12B).
-clauses(Type, Hook, Cs) ->
- {prefer_nl,[$;],lexprs(Cs, Type, Hook)}.
+clauses(Type, Opts, Cs) ->
+ {prefer_nl,[$;],lexprs(Cs, Type, Opts)}.
-%% lc_quals(Qualifiers, After, Hook)
+%% lc_quals(Qualifiers, After, Opts)
%% List comprehension qualifiers (breaks lines since R12B).
-lc_quals(Qs, Hook) ->
- {prefer_nl,[$,],lexprs(Qs, fun lc_qual/2, Hook)}.
+lc_quals(Qs, Opts) ->
+ {prefer_nl,[$,],lexprs(Qs, fun lc_qual/2, Opts)}.
-lc_qual({b_generate,_,Pat,E}, Hook) ->
- Pl = lexpr(Pat, 0, Hook),
- {list,[{step,[Pl,leaf(" <=")],lexpr(E, 0, Hook)}]};
-lc_qual({generate,_,Pat,E}, Hook) ->
- Pl = lexpr(Pat, 0, Hook),
- {list,[{step,[Pl,leaf(" <-")],lexpr(E, 0, Hook)}]};
-lc_qual(Q, Hook) ->
- lexpr(Q, 0, Hook).
+lc_qual({b_generate,_,Pat,E}, Opts) ->
+ Pl = lexpr(Pat, 0, Opts),
+ {list,[{step,[Pl,leaf(" <=")],lexpr(E, 0, Opts)}]};
+lc_qual({generate,_,Pat,E}, Opts) ->
+ Pl = lexpr(Pat, 0, Opts),
+ {list,[{step,[Pl,leaf(" <-")],lexpr(E, 0, Opts)}]};
+lc_qual(Q, Opts) ->
+ lexpr(Q, 0, Opts).
-proper_list(Es, Hook) ->
- {seq,$[,$],$,,lexprs(Es, Hook)}.
+proper_list(Es, Opts) ->
+ {seq,$[,$],$,,lexprs(Es, Opts)}.
-improper_list(Es, Hook) ->
- {seq,$[,$],{$,,$|},lexprs(Es, Hook)}.
+improper_list(Es, Opts) ->
+ {seq,$[,$],{$,,$|},lexprs(Es, Opts)}.
-tuple(L, Hook) ->
- tuple(L, fun lexpr/2, Hook).
+tuple(L, Opts) ->
+ tuple(L, fun lexpr/2, Opts).
-tuple(Es, F, Hook) ->
- {seq,${,$},$,,lexprs(Es, F, Hook)}.
+tuple(Es, F, Opts) ->
+ {seq,${,$},$,,lexprs(Es, F, Opts)}.
-args(As, Hook) ->
- {seq,$(,$),[$,],lexprs(As, Hook)}.
+args(As, Opts) ->
+ {seq,$(,$),[$,],lexprs(As, Opts)}.
-expr_list(Es, Sep, F, Hook) ->
- {seq,[],[],Sep,lexprs(Es, F, Hook)}.
+expr_list(Es, Sep, F, Opts) ->
+ {seq,[],[],Sep,lexprs(Es, F, Opts)}.
-lexprs(Es, Hook) ->
- lexprs(Es, fun lexpr/2, Hook).
+lexprs(Es, Opts) ->
+ lexprs(Es, fun lexpr/2, Opts).
-lexprs(Es, F, Hook) ->
- [F(E, Hook) || E <- Es].
+lexprs(Es, F, Opts) ->
+ [F(E, Opts) || E <- Es].
maybe_paren(P, Prec, Expr) when P < Prec ->
[$(,Expr,$)];
@@ -781,13 +806,13 @@ leaf(S) ->
%%% Do the formatting. Currently nothing fancy. Could probably have
%%% done it in one single pass.
-frmt(Item) ->
- frmt(Item, 0).
+frmt(Item, PP) ->
+ frmt(Item, 0, PP).
-frmt(Item, I) ->
+frmt(Item, I, PP) ->
ST = spacetab(),
WT = wordtable(),
- {Chars,_Length} = f(Item, I, ST, WT),
+ {Chars,_Length} = f(Item, I, ST, WT, PP),
[Chars].
%%% What the tags mean:
@@ -803,6 +828,7 @@ frmt(Item, I) ->
%%% - {force_nl,ExtraInfo,I}: fun-info (a comment) forces linebreak before I.
%%% - {prefer_nl,Sep,IPs}: forces linebreak between Is unlesss negative
%%% indentation.
+%%% - {char,C}: a character
%%% - {string,S}: a string.
%%% - {hook,...}, {ehook,...}: hook expressions.
%%%
@@ -812,22 +838,22 @@ frmt(Item, I) ->
%%% cstep works similarly, but no linebreak if the width of I1 is less
%%% than the indentation (this is for "A = <expression over several lines>).
-f([]=Nil, _I0, _ST, _WT) ->
+f([]=Nil, _I0, _ST, _WT, _PP) ->
{Nil,0};
-f(C, _I0, _ST, _WT) when is_integer(C) ->
+f(C, _I0, _ST, _WT, _PP) when is_integer(C) ->
{C,1};
-f({leaf,Length,Chars}, _I0, _ST, _WT) ->
+f({leaf,Length,Chars}, _I0, _ST, _WT, _PP) ->
{Chars,Length};
-f([Item|Items], I0, ST, WT) ->
- consecutive(Items, f(Item, I0, ST, WT), I0, ST, WT);
-f({list,Items}, I0, ST, WT) ->
- f({seq,[],[],[[]],Items}, I0, ST, WT);
-f({first,E,Item}, I0, ST, WT) ->
- f({seq,E,[],[[]],[Item]}, I0, ST, WT);
-f({seq,Before,After,Sep,LItems}, I0, ST, WT) ->
- BCharsSize = f(Before, I0, ST, WT),
+f([Item|Items], I0, ST, WT, PP) ->
+ consecutive(Items, f(Item, I0, ST, WT, PP), I0, ST, WT, PP);
+f({list,Items}, I0, ST, WT, PP) ->
+ f({seq,[],[],[[]],Items}, I0, ST, WT, PP);
+f({first,E,Item}, I0, ST, WT, PP) ->
+ f({seq,E,[],[[]],[Item]}, I0, ST, WT, PP);
+f({seq,Before,After,Sep,LItems}, I0, ST, WT, PP) ->
+ BCharsSize = f(Before, I0, ST, WT, PP),
I = indent(BCharsSize, I0),
- CharsSizeL = fl(LItems, Sep, I, After, ST, WT),
+ CharsSizeL = fl(LItems, Sep, I, After, ST, WT, PP),
{CharsL,SizeL} = unz(CharsSizeL),
{BCharsL,BSizeL} = unz1([BCharsSize]),
Sizes = BSizeL ++ SizeL,
@@ -848,15 +874,15 @@ f({seq,Before,After,Sep,LItems}, I0, ST, WT) ->
{BCharsL++insert_newlines(CharsSizeL, I, ST),
nsz(lists:last(Sizes), I0)}
end;
-f({force_nl,_ExtraInfoItem,Item}, I, ST, WT) when I < 0 ->
+f({force_nl,_ExtraInfoItem,Item}, I, ST, WT, PP) when I < 0 ->
%% Extra info is a comment; cannot have that on the same line
- f(Item, I, ST, WT);
-f({force_nl,ExtraInfoItem,Item}, I, ST, WT) ->
- f({prefer_nl,[],[ExtraInfoItem,Item]}, I, ST, WT);
-f({prefer_nl,Sep,LItems}, I, ST, WT) when I < 0 ->
- f({seq,[],[],Sep,LItems}, I, ST, WT);
-f({prefer_nl,Sep,LItems}, I0, ST, WT) ->
- CharsSize2L = fl(LItems, Sep, I0, [], ST, WT),
+ f(Item, I, ST, WT, PP);
+f({force_nl,ExtraInfoItem,Item}, I, ST, WT, PP) ->
+ f({prefer_nl,[],[ExtraInfoItem,Item]}, I, ST, WT, PP);
+f({prefer_nl,Sep,LItems}, I, ST, WT, PP) when I < 0 ->
+ f({seq,[],[],Sep,LItems}, I, ST, WT, PP);
+f({prefer_nl,Sep,LItems}, I0, ST, WT, PP) ->
+ CharsSize2L = fl(LItems, Sep, I0, [], ST, WT, PP),
{_CharsL,Sizes} = unz(CharsSize2L),
if
Sizes =:= [] ->
@@ -864,37 +890,40 @@ f({prefer_nl,Sep,LItems}, I0, ST, WT) ->
true ->
{insert_newlines(CharsSize2L, I0, ST),nsz(lists:last(Sizes), I0)}
end;
-f({string,S}, I, ST, WT) ->
- f(write_a_string(S, I), I, ST, WT);
-f({hook,HookExpr,Precedence,Func}, I, _ST, _WT) ->
- Chars = Func(HookExpr, I, Precedence, Func),
+f({char,C}, I, ST, WT, PP) ->
+ f(write_a_char(C, PP), I, ST, WT, PP);
+f({string,S}, I, ST, WT, PP) ->
+ f(write_a_string(S, I, PP), I, ST, WT, PP);
+f({hook,HookExpr,Precedence,Func,Options}, I, _ST, _WT, _PP) ->
+ Chars = Func(HookExpr, I, Precedence, Options),
{Chars,indentation(Chars, I)};
-f({ehook,HookExpr,Precedence,{Mod,Func,Eas}=ModFuncEas}, I, _ST, _WT) ->
+f({ehook,HookExpr,Precedence,{Mod,Func,Eas}=ModFuncEas}, I, _ST, _WT, _PP) ->
Chars = apply(Mod, Func, [HookExpr,I,Precedence,ModFuncEas|Eas]),
{Chars,indentation(Chars, I)};
-f(WordName, _I, _ST, WT) -> % when is_atom(WordName)
+f(WordName, _I, _ST, WT, _PP) -> % when is_atom(WordName)
word(WordName, WT).
-define(IND, 4).
%% fl(ListItems, I0, ST, WT) -> [[CharsSize1,CharsSize2]]
%% ListItems = [{Item,Items}|Item]
-fl([], _Sep, I0, After, ST, WT) ->
- [[f(After, I0, ST, WT),{[],0}]];
-fl(CItems, Sep0, I0, After, ST, WT) ->
+fl([], _Sep, I0, After, ST, WT, PP) ->
+ [[f(After, I0, ST, WT, PP),{[],0}]];
+fl(CItems, Sep0, I0, After, ST, WT, PP) ->
F = fun({step,Item1,Item2}, S) ->
- [f(Item1, I0, ST, WT),f([Item2,S], incr(I0, ?IND), ST, WT)];
+ [f(Item1, I0, ST, WT, PP),
+ f([Item2,S], incr(I0, ?IND), ST, WT, PP)];
({cstep,Item1,Item2}, S) ->
- {_,Sz1} = CharSize1 = f(Item1, I0, ST, WT),
+ {_,Sz1} = CharSize1 = f(Item1, I0, ST, WT, PP),
if
is_integer(Sz1), Sz1 < ?IND ->
Item2p = [leaf("\s"),Item2,S],
- [consecutive(Item2p, CharSize1, I0, ST, WT),{[],0}];
+ [consecutive(Item2p, CharSize1, I0, ST, WT, PP),{[],0}];
true ->
- [CharSize1,f([Item2,S], incr(I0, ?IND), ST, WT)]
+ [CharSize1,f([Item2,S], incr(I0, ?IND), ST, WT, PP)]
end;
(Item, S) ->
- [f([Item,S], I0, ST, WT),{[],0}]
+ [f([Item,S], I0, ST, WT, PP),{[],0}]
end,
{Sep,LastSep} = case Sep0 of {_,_} -> Sep0; _ -> {Sep0,Sep0} end,
fl1(CItems, F, Sep, LastSep, After).
@@ -906,10 +935,10 @@ fl1([CItem1,CItem2], F, _Sep, LastSep, After) ->
fl1([CItem|CItems], F, Sep, LastSep, After) ->
[F(CItem, Sep)|fl1(CItems, F, Sep, LastSep, After)].
-consecutive(Items, CharSize1, I0, ST, WT) ->
+consecutive(Items, CharSize1, I0, ST, WT, PP) ->
{CharsSizes,_Length} =
mapfoldl(fun(Item, Len) ->
- CharsSize = f(Item, Len, ST, WT),
+ CharsSize = f(Item, Len, ST, WT, PP),
{CharsSize,indent(CharsSize, Len)}
end, indent(CharSize1, I0), Items),
{CharsL,SizeL} = unz1([CharSize1|CharsSizes]),
@@ -999,26 +1028,40 @@ has_nl([C|Cs]) ->
has_nl([]) ->
false.
+write_a_char(C, PP) ->
+ flat_leaf(write_char(C, PP)).
+
-define(MIN_SUBSTRING, 5).
-write_a_string(S, I) when I < 0; S =:= [] ->
- leaf(write_string(S));
-write_a_string(S, I) ->
+write_a_string(S, I, PP) when I < 0; S =:= [] ->
+ flat_leaf(write_string(S, PP));
+write_a_string(S, I, PP) ->
Len = erlang:max(?MAXLINE-I, ?MIN_SUBSTRING),
- {list,write_a_string(S, Len, Len)}.
+ {list,write_a_string(S, Len, Len, PP)}.
-write_a_string([], _N, _Len) ->
+write_a_string([], _N, _Len, _PP) ->
[];
-write_a_string(S, N, Len) ->
+write_a_string(S, N, Len, PP) ->
SS = string:sub_string(S, 1, N),
- Sl = write_string(SS),
- case (iolist_size(Sl) > Len) and (N > ?MIN_SUBSTRING) of
+ Sl = write_string(SS, PP),
+ case (length(Sl) > Len) and (N > ?MIN_SUBSTRING) of
true ->
- write_a_string(S, N-1, Len);
+ write_a_string(S, N-1, Len, PP);
false ->
- [leaf(Sl)|write_a_string(lists:nthtail(length(SS), S), Len, Len)]
+ [flat_leaf(Sl) |
+ write_a_string(lists:nthtail(length(SS), S), Len, Len, PP)]
end.
+flat_leaf(S) ->
+ L = lists:flatten(S),
+ {leaf,length(L),L}.
+
+write_string(S, PP) ->
+ lists:flatten((PP#pp.string_fun)(S)).
+
+write_char(C, PP) ->
+ lists:flatten((PP#pp.char_fun)(C)).
+
%%
%% Utilities
%%
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index 0c8735bb6d..e5bb287c45 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -32,19 +33,19 @@
%% 173 - 176 { - ~ punctuation
%% 177 DEL control
%% 200 - 237 control
-%% 240 - 277 NBSP - � punctuation
-%% 300 - 326 � - � uppercase
-%% 327 � punctuation
-%% 330 - 336 � - � uppercase
-%% 337 - 366 � - � lowercase
-%% 367 � punctuation
-%% 370 - 377 � - � lowercase
+%% 240 - 277 NBSP - ¿ punctuation
+%% 300 - 326 À - Ö uppercase
+%% 327 × punctuation
+%% 330 - 336 Ø - Þ uppercase
+%% 337 - 366 ß - ö lowercase
+%% 367 ÷ punctuation
+%% 370 - 377 ø - ÿ lowercase
%%
%% Many punctuation characters have special meaning:
%% $\s, $_, $", $$, $%, $', $.
%% DEL is a punctuation.
%%
-%% Must watch using � \327, very close to x \170.
+%% Must watch using × \327, very close to x \170.
-module(erl_scan).
@@ -55,7 +56,15 @@
token_info/1,token_info/2,
attributes_info/1,attributes_info/2,set_attribute/3]).
--export_type([error_info/0, line/0, return_cont/0, tokens_result/0]).
+%%% Private
+-export([continuation_location/1]).
+
+-export_type([error_info/0,
+ line/0,
+ location/0,
+ options/0,
+ return_cont/0,
+ tokens_result/0]).
%%%
%%% Defines and type definitions
@@ -74,7 +83,8 @@
-type location() :: line() | {line(),column()}.
-type resword_fun() :: fun((atom()) -> boolean()).
-type option() :: 'return' | 'return_white_spaces' | 'return_comments'
- | 'text' | {'reserved_word_fun', resword_fun()}.
+ | 'text' | {'reserved_word_fun', resword_fun()}
+ | 'unicode'.
-type options() :: option() | [option()].
-type symbol() :: atom() | float() | integer() | string().
-type info_line() :: integer() | term().
@@ -95,7 +105,8 @@
{resword_fun = fun reserved_word/1 :: resword_fun(),
ws = false :: boolean(),
comment = false :: boolean(),
- text = false :: boolean()}).
+ text = false :: boolean(),
+ unicode = false :: boolean()}).
%%----------------------------------------------------------------------------
@@ -183,6 +194,11 @@ tokens({erl_scan_continuation,Cs,Col,Toks,Line,St,Any,Fun},
CharSpec, _Loc, _Opts) ->
tokens1(Cs++CharSpec, St, Line, Col, Toks, Fun, Any).
+continuation_location({erl_scan_continuation,_,no_col,_,Line,_,_,_}) ->
+ Line;
+continuation_location({erl_scan_continuation,_,Col,_,Line,_,_,_}) ->
+ {Line,Col}.
+
-type attribute_item() :: 'column' | 'length' | 'line'
| 'location' | 'text'.
-type info_location() :: location() | term().
@@ -201,15 +217,14 @@ token_info(Token) ->
Items = [category,column,length,line,symbol,text], % undefined order
token_info(Token, Items).
--spec token_info(Token, TokenItem) -> TokenInfo | 'undefined' when
- Token :: token(),
- TokenItem :: token_item(),
- TokenInfo :: TokenInfoTuple :: token_info();
- (Token, TokenItems) -> [TokenInfo] when
- Token :: token(),
- TokenItems :: [TokenItem],
- TokenItem :: token_item(),
- TokenInfo :: [TokenInfoTuple :: token_info()].
+-spec token_info(Token, TokenItem) -> TokenInfoTuple | 'undefined' when
+ Token :: token(),
+ TokenItem :: token_item(),
+ TokenInfoTuple :: token_info();
+ (Token, TokenItems) -> TokenInfo when
+ Token :: token(),
+ TokenItems :: [TokenItem :: token_item()],
+ TokenInfo :: [TokenInfoTuple :: token_info()].
token_info(_Token, []) ->
[];
token_info(Token, [Item|Items]) when is_atom(Item) ->
@@ -239,16 +254,15 @@ attributes_info(Attributes) ->
Items = [column,length,line,text], % undefined order
attributes_info(Attributes, Items).
--spec attributes_info(Attributes, AttributeItem) ->
- AttributeInfo | 'undefined' when
- Attributes :: attributes(),
- AttributeItem :: attribute_item(),
- AttributeInfo :: AttributeInfoTuple :: attribute_info();
- (Attributes, AttributeItems) -> [AttributeInfo] when
- Attributes :: attributes(),
- AttributeItems :: [AttributeItem],
- AttributeItem :: attribute_item(),
- AttributeInfo :: [AttributeInfoTuple :: attribute_info()].
+-spec attributes_info
+ (Attributes, AttributeItem) -> AttributeInfoTuple | 'undefined' when
+ Attributes :: attributes(),
+ AttributeItem :: attribute_item(),
+ AttributeInfoTuple :: attribute_info();
+ (Attributes, AttributeItems) -> AttributeInfo when
+ Attributes :: attributes(),
+ AttributeItems :: [AttributeItem :: attribute_item()],
+ AttributeInfo :: [AttributeInfoTuple :: attribute_info()].
attributes_info(_Attrs, []) ->
[];
attributes_info(Attrs, [A|As]) when is_atom(A) ->
@@ -324,13 +338,20 @@ string_thing(_) -> "string".
(C >= $\000 andalso C =< $\s orelse C >= $\200 andalso C =< $\240)).
-define(DIGIT(C), C >= $0, C =< $9).
-define(CHAR(C), is_integer(C), C >= 0).
-
-%% A workaround: Unicode strings are not returned as strings, but as
-%% lists of integers. For instance, "b\x{aaa}c" => [98,2730,99]. This
-%% is to protect the system from character codes greater than 255. To
-%% be removed. Search for UNI to find workaround code.
+-define(UNICODE(C),
+ (C >= 0 andalso C < 16#D800 orelse
+ C > 16#DFFF andalso C < 16#FFFE orelse
+ C > 16#FFFF andalso C =< 16#10FFFF)).
+
+%% When the option 'unicode' is false: return Unicode strings as lists
+%% of integers and Unicode characters as integers. For instance,
+%% erl_scan:string("\"b\x{aaa}c\".") is equivalent to
+%% erl_scan:string("[98,2730,99]."). This is to protect the caller
+%% from character codes greater than 255. Search for UNI to find code
+%% implementing this "feature". The 'unicode' option is undocumented
+%% and will probably be removed later.
-define(NO_UNICODE, 0).
--define(UNI255(C), (C) =< 16#ff).
+-define(UNI255(C), (C =< 16#ff)).
options(Opts0) when is_list(Opts0) ->
Opts = lists:foldr(fun expand_opt/2, [], Opts0),
@@ -344,10 +365,12 @@ 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),
+ Unicode = proplists:get_bool(unicode, Opts),
#erl_scan{resword_fun = RW_fun,
comment = Comment,
ws = WS,
- text = Txt};
+ text = Txt,
+ unicode = Unicode};
options(Opt) ->
options([Opt]).
@@ -513,9 +536,9 @@ scan1([$$|Cs], St, Line, Col, Toks) ->
scan_char(Cs, St, Line, Col, Toks);
scan1([$\r|Cs], St, Line, Col, Toks) when St#erl_scan.ws ->
white_space_end(Cs, St, Line, Col, Toks, 1, "\r");
-scan1([C|Cs], St, Line, Col, Toks) when C >= $�, C =< $�, C =/= $� ->
+scan1([C|Cs], St, Line, Col, Toks) when C >= $ß, C =< $ÿ, C =/= $÷ ->
scan_atom(Cs, St, Line, Col, Toks, [C]);
-scan1([C|Cs], St, Line, Col, Toks) when C >= $�, C =< $�, C /= $� ->
+scan1([C|Cs], St, Line, Col, Toks) when C >= $À, C =< $Þ, C /= $× ->
scan_variable(Cs, St, Line, Col, Toks, [C]);
scan1([$\t|Cs], St, Line, Col, Toks) when St#erl_scan.ws ->
scan_tabs(Cs, St, Line, Col, Toks, 1);
@@ -628,15 +651,12 @@ scan1([$~|Cs], St, Line, Col, Toks) ->
scan1([$&|Cs], St, Line, Col, Toks) ->
tok2(Cs, St, Line, Col, Toks, "&", '&', 1);
%% End of optimization.
-scan1([C|Cs], St, Line, Col, Toks) when ?CHAR(C) ->
+scan1([C|Cs], St, Line, Col, Toks) when ?CHAR(C), ?UNI255(C) ->
Str = [C],
- case catch list_to_atom(Str) of
- Sym when is_atom(Sym) ->
- tok2(Cs, St, Line, Col, Toks, Str, Sym, 1);
- _ ->
- Ncol = incr_column(Col, 1),
- scan_error({illegal,character}, Line, Col, Line, Ncol, Cs)
- end;
+ tok2(Cs, St, Line, Col, Toks, Str, list_to_atom(Str), 1);
+scan1([C|Cs], _St, Line, Col, _Toks) when ?CHAR(C) ->
+ Ncol = incr_column(Col, 1),
+ scan_error({illegal,character}, Line, Col, Line, Ncol, Cs);
scan1([]=Cs, _St, Line, Col, Toks) ->
{more,{Cs,Col,Toks,Line,[],fun scan/6}};
scan1(eof=Cs, _St, Line, Col, Toks) ->
@@ -685,9 +705,9 @@ scan_name([C|Cs], Ncs) when ?DIGIT(C) ->
scan_name(Cs, [C|Ncs]);
scan_name([$@=C|Cs], Ncs) ->
scan_name(Cs, [C|Ncs]);
-scan_name([C|Cs], Ncs) when C >= $�, C =< $�, C =/= $� ->
+scan_name([C|Cs], Ncs) when C >= $ß, C =< $ÿ, C =/= $÷ ->
scan_name(Cs, [C|Ncs]);
-scan_name([C|Cs], Ncs) when C >= $�, C =< $�, C =/= $� ->
+scan_name([C|Cs], Ncs) when C >= $À, C =< $Þ, C =/= $× ->
scan_name(Cs, [C|Ncs]);
scan_name([], Ncs) ->
{more,Ncs};
@@ -834,32 +854,44 @@ scan_char([$\\|Cs]=Cs0, St, Line, Col, Toks) ->
{eof,Ncol} ->
scan_error(char, Line, Col, Line, Ncol, eof);
{nl,Val,Str,Ncs,Ncol} ->
- Attrs = attributes(Line, Col, St, "$\\"++Str),
+ Attrs = attributes(Line, Col, St, "$\\"++Str), %"
Ntoks = [{char,Attrs,Val}|Toks],
scan1(Ncs, St, Line+1, Ncol, Ntoks);
{unicode,Val,Str,Ncs,Ncol} ->
- Attrs = attributes(Line, Col, St, "$\\"++Str),
- Ntoks = [{integer,Attrs,Val}|Toks], % UNI
+ Attrs = attributes(Line, Col, St, "$\\"++Str), %"
+ Tag = char_tag(Val, St), % UNI
+ Ntoks = [{Tag,Attrs,Val}|Toks],
scan1(Ncs, St, Line, Ncol, Ntoks);
{Val,Str,Ncs,Ncol} ->
- Attrs = attributes(Line, Col, St, "$\\"++Str),
+ Attrs = attributes(Line, Col, St, "$\\"++Str), %"
Ntoks = [{char,Attrs,Val}|Toks],
scan1(Ncs, St, Line, Ncol, Ntoks)
end;
scan_char([$\n=C|Cs], St, Line, Col, Toks) ->
Attrs = attributes(Line, Col, St, [$$,C]),
scan1(Cs, St, Line+1, new_column(Col, 1), [{char,Attrs,C}|Toks]);
-scan_char([C|Cs], St, Line, Col, Toks) when ?CHAR(C) ->
- Tag = if ?UNI255(C) -> char; true -> integer end, % UNI
+scan_char([C|Cs], St, Line, Col, Toks) when ?UNICODE(C) ->
+ Tag = char_tag(C, St), % UNI
Attrs = attributes(Line, Col, St, [$$,C]),
scan1(Cs, St, Line, incr_column(Col, 2), [{Tag,Attrs,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);
scan_char([], _St, Line, Col, Toks) ->
{more,{[$$],Col,Toks,Line,[],fun scan/6}};
scan_char(eof, _St, Line, Col, _Toks) ->
scan_error(char, Line, Col, Line, incr_column(Col, 1), eof).
+-compile({inline,[char_tag/2]}).
+
+char_tag(C, _St) when ?UNI255(C) ->
+ char;
+char_tag(_C, #erl_scan{unicode = true}) ->
+ char;
+char_tag(_C, _St) ->
+ integer.
+
scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0,Uni0}) ->
- case scan_string0(Cs, St, Line, Col, $\", Str, Wcs, Uni0) of
+ case scan_string0(Cs, St, Line, Col, $\", true, Str, Wcs, Uni0) of %"
{more,Ncs,Nline,Ncol,Nstr,Nwcs,Uni} ->
State = {Nwcs,Nstr,Line0,Col0,Uni},
{more,{Ncs,Ncol,Toks,Nline,State,fun scan_string/6}};
@@ -867,8 +899,9 @@ scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0,Uni0}) ->
scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs);
{error,Nline,Ncol,Nwcs,Ncs} ->
Estr = string:substr(Nwcs, 1, 16), % Expanded escape chars.
- scan_error({string,$\",Estr}, Line0, Col0, Nline, Ncol, Ncs);
- {Ncs,Nline,Ncol,Nstr,Nwcs,?NO_UNICODE} ->
+ scan_error({string,$\",Estr}, Line0, Col0, Nline, Ncol, Ncs); %"
+ {Ncs,Nline,Ncol,Nstr,Nwcs,Uni} when Uni =:= ?NO_UNICODE;
+ St#erl_scan.unicode ->
Attrs = attributes(Line0, Col0, St, Nstr),
scan1(Ncs, St, Nline, Ncol, [{string,Attrs,Nwcs}|Toks]);
{Ncs,Nline,Ncol,Nstr,_Nwcs,_Uni} ->
@@ -920,7 +953,8 @@ unicode_tokens(Line, Col, Str, Val, St, Toks, Cs, Cline, Ccol) ->
[{',',attributes(Cline, Ccol, St, "")} || Cs =/= "\""] ++ [Token|Toks].
scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0,Uni0}) ->
- case scan_string0(Cs, St, Line, Col, $\', Str, Wcs, Uni0) of
+ AllowUni = St#erl_scan.unicode,
+ case scan_string0(Cs, St, Line, Col, $\', AllowUni, Str, Wcs, Uni0) of %'
{more,Ncs,Nline,Ncol,Nstr,Nwcs,Uni} ->
State = {Nwcs,Nstr,Line0,Col0,Uni},
{more,{Ncs,Ncol,Toks,Nline,State,fun scan_qatom/6}};
@@ -928,8 +962,9 @@ scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0,Uni0}) ->
scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs);
{error,Nline,Ncol,Nwcs,Ncs} ->
Estr = string:substr(Nwcs, 1, 16), % Expanded escape chars.
- scan_error({string,$\',Estr}, Line0, Col0, Nline, Ncol, Ncs);
- {Ncs,Nline,Ncol,Nstr,Nwcs,?NO_UNICODE} ->
+ scan_error({string,$\',Estr}, Line0, Col0, Nline, Ncol, Ncs); %'
+ {Ncs,Nline,Ncol,Nstr,Nwcs,Uni} ->
+ true = Uni =:= ?NO_UNICODE orelse AllowUni,
case catch list_to_atom(Nwcs) of
A when is_atom(A) ->
Attrs = attributes(Line0, Col0, St, Nstr),
@@ -939,38 +974,40 @@ scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0,Uni0}) ->
end
end.
-scan_string0(Cs, #erl_scan{text=false}, Line, no_col=Col, Q, [], Wcs, Uni) ->
- scan_string_no_col(Cs, Line, Col, Q, Wcs, Uni);
-scan_string0(Cs, #erl_scan{text=true}, Line, no_col=Col, Q, Str, Wcs, Uni) ->
- scan_string1(Cs, Line, Col, Q, Str, Wcs, Uni);
-scan_string0(Cs, _St, Line, Col, Q, [], Wcs, Uni) ->
- scan_string_col(Cs, Line, Col, Q, Wcs, Uni);
-scan_string0(Cs, _St, Line, Col, Q, Str, Wcs, Uni) ->
- scan_string1(Cs, Line, Col, Q, Str, Wcs, Uni).
+scan_string0(Cs, #erl_scan{text=false}, Line, no_col=Col, Q, U, [], Wcs, Uni) ->
+ scan_string_no_col(Cs, Line, Col, Q, U, Wcs, Uni);
+scan_string0(Cs, #erl_scan{text=true}, Line, no_col=Col, Q, U, Str, Wcs, Uni) ->
+ scan_string1(Cs, Line, Col, Q, U, Str, Wcs, Uni);
+scan_string0(Cs, _St, Line, Col, Q, U, [], Wcs, Uni) ->
+ scan_string_col(Cs, Line, Col, Q, U, Wcs, Uni);
+scan_string0(Cs, _St, Line, Col, Q, U, Str, Wcs, Uni) ->
+ scan_string1(Cs, Line, Col, Q, U, Str, Wcs, Uni).
%% Optimization. Col =:= no_col.
-scan_string_no_col([Q|Cs], Line, Col, Q, Wcs, Uni) ->
+scan_string_no_col([Q|Cs], Line, Col, Q, _U, Wcs, Uni) ->
{Cs,Line,Col,_DontCare=[],lists:reverse(Wcs),Uni};
-scan_string_no_col([$\n=C|Cs], Line, Col, Q, Wcs, Uni) ->
- scan_string_no_col(Cs, Line+1, Col, Q, [C|Wcs], Uni);
-scan_string_no_col([C|Cs], Line, Col, Q, Wcs, Uni) when C =/= $\\,
- ?CHAR(C), ?UNI255(C) ->
- scan_string_no_col(Cs, Line, Col, Q, [C|Wcs], Uni);
-scan_string_no_col(Cs, Line, Col, Q, Wcs, Uni) ->
- scan_string1(Cs, Line, Col, Q, Wcs, Wcs, Uni).
+scan_string_no_col([$\n=C|Cs], Line, Col, Q, U, Wcs, Uni) ->
+ scan_string_no_col(Cs, Line+1, Col, Q, U, [C|Wcs], Uni);
+scan_string_no_col([C|Cs], Line, Col, Q, U, Wcs, Uni) when C =/= $\\,
+ ?CHAR(C),
+ ?UNI255(C) ->
+ scan_string_no_col(Cs, Line, Col, Q, U, [C|Wcs], Uni);
+scan_string_no_col(Cs, Line, Col, Q, U, Wcs, Uni) ->
+ scan_string1(Cs, Line, Col, Q, U, Wcs, Wcs, Uni).
%% Optimization. Col =/= no_col.
-scan_string_col([Q|Cs], Line, Col, Q, Wcs0, Uni) ->
+scan_string_col([Q|Cs], Line, Col, Q, _U, Wcs0, Uni) ->
Wcs = lists:reverse(Wcs0),
Str = [Q|Wcs++[Q]],
{Cs,Line,Col+1,Str,Wcs,Uni};
-scan_string_col([$\n=C|Cs], Line, _xCol, Q, Wcs, Uni) ->
- scan_string_col(Cs, Line+1, 1, Q, [C|Wcs], Uni);
-scan_string_col([C|Cs], Line, Col, Q, Wcs, Uni) when C =/= $\\,
- ?CHAR(C), ?UNI255(C) ->
- scan_string_col(Cs, Line, Col+1, Q, [C|Wcs], Uni);
-scan_string_col(Cs, Line, Col, Q, Wcs, Uni) ->
- scan_string1(Cs, Line, Col, Q, Wcs, Wcs, Uni).
+scan_string_col([$\n=C|Cs], Line, _xCol, Q, U, Wcs, Uni) ->
+ scan_string_col(Cs, Line+1, 1, Q, U, [C|Wcs], Uni);
+scan_string_col([C|Cs], Line, Col, Q, U, Wcs, Uni) when C =/= $\\,
+ ?CHAR(C),
+ ?UNI255(C) ->
+ scan_string_col(Cs, Line, Col+1, Q, U, [C|Wcs], Uni);
+scan_string_col(Cs, Line, Col, Q, U, Wcs, Uni) ->
+ scan_string1(Cs, Line, Col, Q, U, Wcs, Wcs, Uni).
%% UNI_STR is to be replaced by STR when the Unicode-string-to-list
%% workaround is eventually removed.
@@ -981,14 +1018,14 @@ scan_string_col(Cs, Line, Col, Q, Wcs, Uni) ->
%% but then the end location of the error tuple would not correspond
%% to the start location of the returned Rest string. (Maybe the end
%% location could be modified, but that too is ugly.)
-scan_string1([Q|Cs], Line, Col, Q, Str0, Wcs0, Uni) ->
+scan_string1([Q|Cs], Line, Col, Q, _U, Str0, Wcs0, Uni) ->
Wcs = lists:reverse(Wcs0),
Str = ?UNI_STR(Col, [Q|lists:reverse(Str0, [Q])]),
{Cs,Line,incr_column(Col, 1),Str,Wcs,Uni};
-scan_string1([$\n=C|Cs], Line, Col, Q, Str, Wcs, Uni) ->
+scan_string1([$\n=C|Cs], Line, Col, Q, U, Str, Wcs, Uni) ->
Ncol = new_column(Col, 1),
- scan_string1(Cs, Line+1, Ncol, Q, ?UNI_STR(Col, [C|Str]), [C|Wcs], Uni);
-scan_string1([$\\|Cs]=Cs0, Line, Col, Q, Str, Wcs, Uni) ->
+ scan_string1(Cs, Line+1, Ncol, Q, U, ?UNI_STR(Col, [C|Str]), [C|Wcs], Uni);
+scan_string1([$\\|Cs]=Cs0, Line, Col, Q, U, Str, Wcs, Uni) ->
case scan_escape(Cs, Col) of
more ->
{more,Cs0,Line,Col,Str,Wcs,Uni};
@@ -999,31 +1036,33 @@ scan_string1([$\\|Cs]=Cs0, Line, Col, Q, Str, Wcs, Uni) ->
{nl,Val,ValStr,Ncs,Ncol} ->
Nstr = ?UNI_STR(Ncol, lists:reverse(ValStr, [$\\|Str])),
Nwcs = [Val|Wcs],
- scan_string1(Ncs, Line+1, Ncol, Q, Nstr, Nwcs, Uni);
- {unicode,_Val,_ValStr,Ncs,Ncol} when Q =:= $' -> %' Emacs
+ scan_string1(Ncs, Line+1, Ncol, Q, U, Nstr, Nwcs, Uni);
+ {unicode,_Val,_ValStr,Ncs,Ncol} when not U -> %' Emacs
{char_error,Ncs,{illegal,character},Line,Col,incr_column(Ncol, 1)};
{unicode,Val,ValStr,Ncs,Ncol} -> % UNI. Uni is set to Val.
Nstr = ?UNI_STR(Ncol, lists:reverse(ValStr, [$\\|Str])),
Nwcs = [Val|Wcs], % not used
- scan_string1(Ncs, Line, incr_column(Ncol, 1), Q, Nstr, Nwcs, Val);
+ scan_string1(Ncs, Line, incr_column(Ncol, 1), Q, U, Nstr, Nwcs, Val);
{Val,ValStr,Ncs,Ncol} ->
Nstr = ?UNI_STR(Ncol, lists:reverse(ValStr, [$\\|Str])),
Nwcs = [Val|Wcs],
- scan_string1(Ncs, Line, incr_column(Ncol, 1), Q, Nstr, Nwcs, Uni)
+ scan_string1(Ncs, Line, incr_column(Ncol, 1), Q, U, Nstr, Nwcs, Uni)
end;
-scan_string1([C|Cs], Line, no_col=Col, Q, Str, Wcs, Uni) when ?CHAR(C),
- ?UNI255(C) ->
- %% scan_string1(Cs, Line, Col, Q, Str, [C|Wcs], Uni);
- scan_string1(Cs, Line, Col, Q, [C|Str], [C|Wcs], Uni); % UNI
-scan_string1([C|Cs], Line, Col, Q, Str, Wcs, Uni) when ?CHAR(C), ?UNI255(C) ->
- scan_string1(Cs, Line, Col+1, Q, [C|Str], [C|Wcs], Uni);
-scan_string1([C|Cs], Line, Col, $', _Str, _Wcs, _Uni) when ?CHAR(C) -> %' UNI
+scan_string1([C|Cs], Line, no_col=Col, Q, U, Str, Wcs, Uni) when ?CHAR(C),
+ ?UNI255(C) ->
+ %% scan_string1(Cs, Line, Col, Q, U, Str, [C|Wcs], Uni);
+ scan_string1(Cs, Line, Col, Q, U, [C|Str], [C|Wcs], Uni); % UNI
+scan_string1([C|Cs], Line, Col, Q, U, Str, Wcs, Uni) when ?CHAR(C), ?UNI255(C) ->
+ scan_string1(Cs, Line, Col+1, Q, U, [C|Str], [C|Wcs], Uni);
+scan_string1([C|Cs], Line, Col, _Q, false, _Str, _Wcs, _Uni) when ?CHAR(C) -> %' UNI
+ {char_error,Cs,{illegal,character},Line,Col,incr_column(Col, 1)};
+scan_string1([C|Cs], Line, Col, Q, U, Str, Wcs, _Uni) when ?UNICODE(C) ->
+ scan_string1(Cs, Line, incr_column(Col, 1), Q, U, [C|Str], [C|Wcs], C);
+scan_string1([C|Cs], Line, Col, _Q, _U, _Str, _Wcs, _Uni) when ?CHAR(C) -> % UNI
{char_error,Cs,{illegal,character},Line,Col,incr_column(Col, 1)};
-scan_string1([C|Cs], Line, Col, Q, Str, Wcs, _Uni) when ?CHAR(C) -> % UNI
- scan_string1(Cs, Line, incr_column(Col, 1), Q, [C|Str], [C|Wcs], C);
-scan_string1([]=Cs, Line, Col, _Q, Str, Wcs, Uni) ->
+scan_string1([]=Cs, Line, Col, _Q, _U, Str, Wcs, Uni) ->
{more,Cs,Line,Col,Str,Wcs,Uni};
-scan_string1(eof, Line, Col, _Q, _Str, Wcs, _Uni) ->
+scan_string1(eof, Line, Col, _Q, _U, _Str, Wcs, _Uni) ->
{error,Line,Col,lists:reverse(Wcs),eof}.
-define(OCT(C), C >= $0, C =< $7).
@@ -1074,8 +1113,10 @@ scan_escape([$\n=C|Cs], Col) ->
scan_escape([C0|Cs], Col) when ?CHAR(C0), ?UNI255(C0) ->
C = escape_char(C0),
{C,?UNI_STR(Col, [C0]),Cs,incr_column(Col, 1)};
-scan_escape([C|Cs], Col) when ?CHAR(C) -> % UNI
+scan_escape([C|Cs], Col) when ?UNICODE(C) ->
{unicode,C,?UNI_STR(Col, [C]),Cs,incr_column(Col, 1)};
+scan_escape([C|Cs], Col) when ?CHAR(C) -> % UNI
+ {error,Cs,{illegal,character},incr_column(Col, 1)};
scan_escape([], _Col) ->
more;
scan_escape(eof, Col) ->
@@ -1093,7 +1134,7 @@ scan_esc_end([$}|Cs], Col, Wcs0, B, Str0) ->
case catch erlang:list_to_integer(Wcs, B) of
Val when Val =< 16#FF ->
{Val,?UNI_STR(Col, Str0++Wcs++[$}]),Cs,incr_column(Col, 1)};
- Val when Val =< 16#10FFFF ->
+ Val when ?UNICODE(Val) ->
{unicode,Val,?UNI_STR(Col, Str0++Wcs++[$}]),Cs,incr_column(Col,1)};
_ ->
{error,Cs,{illegal,character},incr_column(Col, 1)}
@@ -1199,18 +1240,36 @@ float_end(Cs, St, Line, Col, Toks, Ncs0) ->
scan_error({illegal,float}, Line, Col, Line, Ncol, Cs)
end.
-skip_comment([C|Cs], St, Line, Col, Toks, N) when C =/= $\n, ?CHAR(C) ->
- skip_comment(Cs, St, Line, Col, Toks, N+1);
-skip_comment([]=Cs, _St, Line, Col, Toks, N) ->
- {more,{Cs,Col,Toks,Line,N,fun skip_comment/6}};
skip_comment(Cs, St, Line, Col, Toks, N) ->
+ skip_comment(Cs, St, Line, Col, Toks, N, St#erl_scan.unicode).
+
+skip_comment([C|Cs], St, Line, Col, Toks, N, U) when C =/= $\n, ?CHAR(C) ->
+ case ?UNI255(C) orelse U andalso ?UNICODE(C) of
+ true ->
+ skip_comment(Cs, St, Line, Col, Toks, N+1, U);
+ false ->
+ Ncol = incr_column(Col, N+1),
+ scan_error({illegal,character}, Line, Col, Line, Ncol, Cs)
+ end;
+skip_comment([]=Cs, _St, Line, Col, Toks, N, _U) ->
+ {more,{Cs,Col,Toks,Line,N,fun skip_comment/6}};
+skip_comment(Cs, St, Line, Col, Toks, N, _U) ->
scan1(Cs, St, Line, incr_column(Col, N), Toks).
-scan_comment([C|Cs], St, Line, Col, Toks, Ncs) when C =/= $\n, ?CHAR(C) ->
- scan_comment(Cs, St, Line, Col, Toks, [C|Ncs]);
-scan_comment([]=Cs, _St, Line, Col, Toks, Ncs) ->
+scan_comment(Cs, St, Line, Col, Toks, Ncs) ->
+ scan_comment(Cs, St, Line, Col, Toks, Ncs, St#erl_scan.unicode).
+
+scan_comment([C|Cs], St, Line, Col, Toks, Ncs, U) when C =/= $\n, ?CHAR(C) ->
+ case ?UNI255(C) orelse U andalso ?UNICODE(C) of
+ true ->
+ scan_comment(Cs, St, Line, Col, Toks, [C|Ncs], U);
+ false ->
+ Ncol = incr_column(Col, length(Ncs)+1),
+ scan_error({illegal,character}, Line, Col, Line, Ncol, Cs)
+ end;
+scan_comment([]=Cs, _St, Line, Col, Toks, Ncs, _U) ->
{more,{Cs,Col,Toks,Line,Ncs,fun scan_comment/6}};
-scan_comment(Cs, St, Line, Col, Toks, Ncs0) ->
+scan_comment(Cs, St, Line, Col, Toks, Ncs0, _U) ->
Ncs = lists:reverse(Ncs0),
tok3(Cs, St, Line, Col, Toks, comment, Ncs, Ncs).
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index 498d850df3..99a9d138ac 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -710,7 +710,7 @@ epp_parse_file2(Epp, S, Forms, Parsed) ->
epp_parse_file(Epp, S, [Form | Forms])
end;
{error,{Ln,Mod,Args}} = Form ->
- io:format("~s:~w: ~s\n",
+ io:format("~s:~w: ~ts\n",
[S#state.file,Ln,Mod:format_error(Args)]),
epp_parse_file(Epp, S#state{n_errors = S#state.n_errors + 1}, [Form | Forms]);
{eof, _LastLine} = Eof ->
@@ -780,10 +780,10 @@ report_errors(Errors) ->
Errors).
list_errors(F, [{Line,Mod,E}|Es]) ->
- io:fwrite("~s:~w: ~s\n", [F,Line,Mod:format_error(E)]),
+ io:fwrite("~s:~w: ~ts\n", [F,Line,Mod:format_error(E)]),
list_errors(F, Es);
list_errors(F, [{Mod,E}|Es]) ->
- io:fwrite("~s: ~s\n", [F,Mod:format_error(E)]),
+ io:fwrite("~s: ~ts\n", [F,Mod:format_error(E)]),
list_errors(F, Es);
list_errors(_F, []) -> ok.
@@ -795,10 +795,10 @@ report_warnings(Ws0) ->
lists:foreach(fun({_,Str}) -> io:put_chars(Str) end, Ws).
format_message(F, [{Line,Mod,E}|Es]) ->
- M = {{F,Line},io_lib:format("~s:~w: Warning: ~s\n", [F,Line,Mod:format_error(E)])},
+ M = {{F,Line},io_lib:format("~s:~w: Warning: ~ts\n", [F,Line,Mod:format_error(E)])},
[M|format_message(F, Es)];
format_message(F, [{Mod,E}|Es]) ->
- M = {none,io_lib:format("~s: Warning: ~s\n", [F,Mod:format_error(E)])},
+ M = {none,io_lib:format("~s: Warning: ~ts\n", [F,Mod:format_error(E)])},
[M|format_message(F, Es)];
format_message(_, []) -> [].
@@ -851,12 +851,27 @@ eval_exprs([E|Es], Bs0, Lf, Ef, RBs) ->
eval_exprs(Es, Bs, Lf, Ef, RBs).
format_exception(Class, Reason) ->
+ Enc = encoding(),
+ P = case Enc of
+ latin1 -> "P";
+ _ -> "tP"
+ end,
PF = fun(Term, I) ->
- io_lib:format("~." ++ integer_to_list(I) ++ "P", [Term, 50])
+ io_lib:format("~." ++ integer_to_list(I) ++ P, [Term, 50])
end,
StackTrace = erlang:get_stacktrace(),
StackFun = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
- lib:format_exception(1, Class, Reason, StackTrace, StackFun, PF).
+ lib:format_exception(1, Class, Reason, StackTrace, StackFun, PF, Enc).
+
+encoding() ->
+ [{encoding, Encoding}] = enc(),
+ Encoding.
+
+enc() ->
+ case lists:keyfind(encoding, 1, io:getopts()) of
+ false -> [{encoding,latin1}]; % should never happen
+ Enc -> [Enc]
+ end.
fatal(Str) ->
throw(Str).
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 59d6de5d10..0c50eb34e6 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -878,7 +878,7 @@ filter_options(_Base, [], Result) ->
%% Gets the source file given path of object code and module name.
get_source_file(Obj, Mod, Rules) ->
- source_by_rules(dirname(Obj), packages:last(Mod), Rules).
+ source_by_rules(dirname(Obj), atom_to_list(Mod), Rules).
source_by_rules(Dir, Base, [{From, To}|Rest]) ->
case try_rule(Dir, Base, From, To) of
diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl
index 391f1cff64..ba35a7170a 100644
--- a/lib/stdlib/src/gb_sets.erl
+++ b/lib/stdlib/src/gb_sets.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -165,7 +166,7 @@
-export([new/0, is_element/2, add_element/2, del_element/2,
subtract/2]).
-%% GB-trees adapted from Sven-Olof Nystr�m's implementation for
+%% GB-trees adapted from Sven-Olof Nyström's implementation for
%% representation of sets.
%%
%% Data structures:
diff --git a/lib/stdlib/src/gb_trees.erl b/lib/stdlib/src/gb_trees.erl
index 258713c90f..de0c239e26 100644
--- a/lib/stdlib/src/gb_trees.erl
+++ b/lib/stdlib/src/gb_trees.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -19,7 +20,7 @@
%% =====================================================================
%% General Balanced Trees - highly efficient dictionaries.
%%
-%% Copyright (C) 1999-2001 Sven-Olof Nystr�m, Richard Carlsson
+%% Copyright (C) 1999-2001 Sven-Olof Nyström, Richard Carlsson
%%
%% An efficient implementation of Prof. Arne Andersson's General
%% Balanced Trees. These have no storage overhead compared to plain
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index 9f65bbfa3a..ecf2aeb375 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,28 +22,28 @@
get_chars/2,get_chars/3,get_line/1,get_line/2,
get_password/0, get_password/1,
setopts/1, setopts/2, getopts/0, getopts/1]).
--export([write/1,write/2,read/1,read/2,read/3]).
+-export([write/1,write/2,read/1,read/2,read/3,read/4]).
-export([columns/0,columns/1,rows/0,rows/1]).
-export([fwrite/1,fwrite/2,fwrite/3,fread/2,fread/3,
format/1,format/2,format/3]).
--export([scan_erl_exprs/1,scan_erl_exprs/2,scan_erl_exprs/3,
- scan_erl_form/1,scan_erl_form/2,scan_erl_form/3,
+-export([scan_erl_exprs/1,scan_erl_exprs/2,scan_erl_exprs/3,scan_erl_exprs/4,
+ scan_erl_form/1,scan_erl_form/2,scan_erl_form/3,scan_erl_form/4,
parse_erl_exprs/1,parse_erl_exprs/2,parse_erl_exprs/3,
- parse_erl_form/1,parse_erl_form/2,parse_erl_form/3]).
+ parse_erl_exprs/4,parse_erl_form/1,parse_erl_form/2,
+ parse_erl_form/3,parse_erl_form/4]).
-export([request/1,request/2,requests/1,requests/2]).
--export_type([device/0, format/0]).
+-export_type([device/0, format/0, server_no_data/0]).
%%-------------------------------------------------------------------------
-type device() :: atom() | pid().
-type prompt() :: atom() | string().
--type error_description() :: term(). % Whatever the io-server sends.
--type request_error() :: {'error',error_description()}.
+%% ErrorDescription is whatever the I/O-server sends.
+-type server_no_data() :: {'error', ErrorDescription :: term()} | 'eof'.
-%% XXX: Some uses of line() in this file may need to read erl_scan:location()
--type line() :: pos_integer().
+-type location() :: erl_scan:location().
%%-------------------------------------------------------------------------
@@ -73,9 +73,9 @@ o_request(Io, Request, Func) ->
put_chars(Chars) ->
put_chars(default_output(), Chars).
--spec put_chars(IoDevice, IoData) -> 'ok' when
+-spec put_chars(IoDevice, CharData) -> 'ok' when
IoDevice :: device(),
- IoData :: unicode:chardata().
+ CharData :: unicode:chardata().
put_chars(Io, Chars) ->
o_request(Io, {put_chars,unicode,Chars}, put_chars).
@@ -124,7 +124,7 @@ rows(Io) ->
{error,enotsup}
end.
--spec get_chars(Prompt, Count) -> Data | 'eof' when
+-spec get_chars(Prompt, Count) -> Data | server_no_data() when
Prompt :: prompt(),
Count :: non_neg_integer(),
Data :: [unicode:unicode_char()] | unicode:unicode_binary().
@@ -132,25 +132,23 @@ rows(Io) ->
get_chars(Prompt, N) ->
get_chars(default_input(), Prompt, N).
--spec get_chars(IoDevice, Prompt, Count) -> Data | 'eof' | {error, Reason} when
+-spec get_chars(IoDevice, Prompt, Count) -> Data | server_no_data() when
IoDevice :: device(),
Prompt :: prompt(),
Count :: non_neg_integer(),
- Reason :: term(),
Data :: [unicode:unicode_char()] | unicode:unicode_binary().
get_chars(Io, Prompt, N) when is_integer(N), N >= 0 ->
request(Io, {get_chars,unicode,Prompt,N}).
--spec get_line(Prompt) -> Data | 'eof' | {'error', Reason} when
+-spec get_line(Prompt) -> Data | server_no_data() when
Prompt :: prompt(),
- Reason :: term(),
Data :: [unicode:unicode_char()] | unicode:unicode_binary().
get_line(Prompt) ->
get_line(default_input(), Prompt).
--spec get_line(IoDevice, Prompt) -> Data | 'eof' | {'error', term()} when
+-spec get_line(IoDevice, Prompt) -> Data | server_no_data() when
IoDevice :: device(),
Prompt :: prompt(),
Data :: [unicode:unicode_char()] | unicode:unicode_binary().
@@ -219,8 +217,9 @@ write(Io, Term) ->
-spec read(Prompt) -> Result when
Prompt :: prompt(),
Result :: {'ok', Term :: term()}
- | 'eof'
- | {'error', ErrorInfo :: erl_scan:error_info()}.
+ | server_no_data()
+ | {'error', ErrorInfo},
+ ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().
% Read does not use get_until as erl_scan does not work with unicode
% XXX:PaN fixme?
@@ -231,8 +230,9 @@ read(Prompt) ->
IoDevice :: device(),
Prompt :: prompt(),
Result :: {'ok', Term :: term()}
- | 'eof'
- | {'error', ErrorInfo :: erl_scan:error_info()}.
+ | server_no_data()
+ | {'error', ErrorInfo},
+ ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().
read(Io, Prompt) ->
case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[1]}) of
@@ -248,24 +248,41 @@ read(Io, Prompt) ->
Other
end.
--spec read(IoDevice, Prompt, StartLine) -> Result when
+-spec read(IoDevice, Prompt, StartLocation) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ StartLocation :: location(),
+ Result :: {'ok', Term :: term(), EndLocation :: location()}
+ | {'eof', EndLocation :: location()}
+ | server_no_data()
+ | {'error', ErrorInfo, ErrorLocation :: location()},
+ ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().
+
+read(Io, Prompt, Pos0) ->
+ read(Io, Prompt, Pos0, []).
+
+-spec read(IoDevice, Prompt, StartLocation, Options) -> Result when
IoDevice :: device(),
Prompt :: prompt(),
- StartLine :: line(),
- Result :: {'ok', Term :: term(), EndLine :: line()}
- | {'eof', EndLine :: line()}
- | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()}.
-
-read(Io, Prompt, StartLine) when is_integer(StartLine) ->
- case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[StartLine]}) of
- {ok,Toks,EndLine} ->
+ StartLocation :: location(),
+ Options :: erl_scan:options(),
+ Result :: {'ok', Term :: term(), EndLocation :: location()}
+ | {'eof', EndLocation :: location()}
+ | server_no_data()
+ | {'error', ErrorInfo, ErrorLocation :: location()},
+ ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().
+
+read(Io, Prompt, Pos0, Options) ->
+ Args = [Pos0,Options],
+ case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,Args}) of
+ {ok,Toks,EndLocation} ->
case erl_parse:parse_term(Toks) of
- {ok,Term} -> {ok,Term,EndLine};
- {error,ErrorInfo} -> {error,ErrorInfo,EndLine}
+ {ok,Term} -> {ok,Term,EndLocation};
+ {error,ErrorInfo} -> {error,ErrorInfo,EndLocation}
end;
- {error,_E,_EndLine} = Error ->
+ {error,_E,_EndLocation} = Error ->
Error;
- {eof,_EndLine} = Eof ->
+ {eof,_EndLocation} = Eof ->
Eof;
Other ->
Other
@@ -313,7 +330,9 @@ fread(Prompt, Format) ->
IoDevice :: device(),
Prompt :: prompt(),
Format :: format(),
- Result :: {'ok', Terms :: [term()]} | 'eof' | {'error', What :: term()}.
+ Result :: {'ok', Terms :: [term()]}
+ | {'error', FreadError :: io_lib:fread_error()}
+ | server_no_data().
fread(Io, Prompt, Format) ->
case request(Io, {fread,Prompt,Format}) of
@@ -348,7 +367,7 @@ format(Io, Format, Args) ->
-spec scan_erl_exprs(Prompt) -> Result when
Prompt :: prompt(),
- Result :: erl_scan:tokens_result() | request_error().
+ Result :: erl_scan:tokens_result() | server_no_data().
scan_erl_exprs(Prompt) ->
scan_erl_exprs(default_input(), Prompt, 1).
@@ -356,23 +375,33 @@ scan_erl_exprs(Prompt) ->
-spec scan_erl_exprs(Device, Prompt) -> Result when
Device :: device(),
Prompt :: prompt(),
- Result :: erl_scan:tokens_result() | request_error().
+ Result :: erl_scan:tokens_result() | server_no_data().
scan_erl_exprs(Io, Prompt) ->
scan_erl_exprs(Io, Prompt, 1).
--spec scan_erl_exprs(Device, Prompt, StartLine) -> Result when
+-spec scan_erl_exprs(Device, Prompt, StartLocation) -> Result when
Device :: device(),
Prompt :: prompt(),
- StartLine :: line(),
- Result :: erl_scan:tokens_result() | request_error().
+ StartLocation :: location(),
+ Result :: erl_scan:tokens_result() | server_no_data().
scan_erl_exprs(Io, Prompt, Pos0) ->
- request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}).
+ scan_erl_exprs(Io, Prompt, Pos0, []).
+
+-spec scan_erl_exprs(Device, Prompt, StartLocation, Options) -> Result when
+ Device :: device(),
+ Prompt :: prompt(),
+ StartLocation :: location(),
+ Options :: erl_scan:options(),
+ Result :: erl_scan:tokens_result() | server_no_data().
+
+scan_erl_exprs(Io, Prompt, Pos0, Options) ->
+ request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0,Options]}).
-spec scan_erl_form(Prompt) -> Result when
Prompt :: prompt(),
- Result :: erl_scan:tokens_result() | request_error().
+ Result :: erl_scan:tokens_result() | server_no_data().
scan_erl_form(Prompt) ->
scan_erl_form(default_input(), Prompt, 1).
@@ -380,26 +409,41 @@ scan_erl_form(Prompt) ->
-spec scan_erl_form(IoDevice, Prompt) -> Result when
IoDevice :: device(),
Prompt :: prompt(),
- Result :: erl_scan:tokens_result() | request_error().
+ Result :: erl_scan:tokens_result() | server_no_data().
scan_erl_form(Io, Prompt) ->
scan_erl_form(Io, Prompt, 1).
--spec scan_erl_form(IoDevice, Prompt, StartLine) -> Result when
+-spec scan_erl_form(IoDevice, Prompt, StartLocation) -> Result when
IoDevice :: device(),
Prompt :: prompt(),
- StartLine :: line(),
- Result :: erl_scan:tokens_result() | request_error().
+ StartLocation :: location(),
+ Result :: erl_scan:tokens_result() | server_no_data().
scan_erl_form(Io, Prompt, Pos0) ->
- request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}).
+ scan_erl_form(Io, Prompt, Pos0, []).
+
+-spec scan_erl_form(IoDevice, Prompt, StartLocation, Options) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ StartLocation :: location(),
+ Options :: erl_scan:options(),
+ Result :: erl_scan:tokens_result() | server_no_data().
+
+scan_erl_form(Io, Prompt, Pos0, Options) ->
+ request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0,Options]}).
%% Parsing Erlang code.
--type parse_ret() :: {'ok', ExprList :: erl_parse:abstract_expr(), EndLine :: line()}
- | {'eof', EndLine :: line()}
- | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()}
- | request_error().
+-type parse_ret() :: {'ok',
+ ExprList :: erl_parse:abstract_expr(),
+ EndLocation :: location()}
+ | {'eof', EndLocation :: location()}
+ | {'error',
+ ErrorInfo :: erl_scan:error_info()
+ | erl_parse:error_info(),
+ ErrorLocation :: location()}
+ | server_no_data().
-spec parse_erl_exprs(Prompt) -> Result when
Prompt :: prompt(),
@@ -416,14 +460,24 @@ parse_erl_exprs(Prompt) ->
parse_erl_exprs(Io, Prompt) ->
parse_erl_exprs(Io, Prompt, 1).
--spec parse_erl_exprs(IoDevice, Prompt, StartLine) -> Result when
+-spec parse_erl_exprs(IoDevice, Prompt, StartLocation) -> Result when
IoDevice :: device(),
Prompt :: prompt(),
- StartLine :: line(),
+ StartLocation :: location(),
Result :: parse_ret().
parse_erl_exprs(Io, Prompt, Pos0) ->
- case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}) of
+ parse_erl_exprs(Io, Prompt, Pos0, []).
+
+-spec parse_erl_exprs(IoDevice, Prompt, StartLocation, Options) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ StartLocation :: location(),
+ Options :: erl_scan:options(),
+ Result :: parse_ret().
+
+parse_erl_exprs(Io, Prompt, Pos0, Options) ->
+ case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0,Options]}) of
{ok,Toks,EndPos} ->
case erl_parse:parse_exprs(Toks) of
{ok,Exprs} -> {ok,Exprs,EndPos};
@@ -433,10 +487,15 @@ parse_erl_exprs(Io, Prompt, Pos0) ->
Other
end.
--type parse_form_ret() :: {'ok', AbsForm :: erl_parse:abstract_form(), EndLine :: line()}
- | {'eof', EndLine :: line()}
- | {'error', ErrorInfo :: erl_scan:error_info(), ErrorLine :: line()}
- | request_error().
+-type parse_form_ret() :: {'ok',
+ AbsForm :: erl_parse:abstract_form(),
+ EndLocation :: location()}
+ | {'eof', EndLocation :: location()}
+ | {'error',
+ ErrorInfo :: erl_scan:error_info()
+ | erl_parse:error_info(),
+ ErrorLocation :: location()}
+ | server_no_data().
-spec parse_erl_form(Prompt) -> Result when
Prompt :: prompt(),
@@ -453,14 +512,25 @@ parse_erl_form(Prompt) ->
parse_erl_form(Io, Prompt) ->
parse_erl_form(Io, Prompt, 1).
--spec parse_erl_form(IoDevice, Prompt, StartLine) -> Result when
+-spec parse_erl_form(IoDevice, Prompt, StartLocation) -> Result when
IoDevice :: device(),
Prompt :: prompt(),
- StartLine :: line(),
+ StartLocation :: location(),
Result :: parse_form_ret().
parse_erl_form(Io, Prompt, Pos0) ->
- case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}) of
+ parse_erl_form(Io, Prompt, Pos0, []).
+
+-spec parse_erl_form(IoDevice, Prompt, StartLocation, Options) -> Result when
+ IoDevice :: device(),
+ Prompt :: prompt(),
+ StartLocation :: location(),
+ Options :: erl_scan:options(),
+ Result :: parse_form_ret().
+
+parse_erl_form(Io, Prompt, Pos0, Options) ->
+ Args = [Pos0, Options],
+ case request(Io, {get_until,unicode,Prompt,erl_scan,tokens,Args}) of
{ok,Toks,EndPos} ->
case erl_parse:parse_form(Toks) of
{ok,Exprs} -> {ok,Exprs,EndPos};
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 513d904c39..5ad505f683 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -46,25 +47,28 @@
%% 173 - 176 { - ~ punctuation
%% 177 DEL control
%% 200 - 237 control
-%% 240 - 277 NBSP - � punctuation
-%% 300 - 326 � - � uppercase
-%% 327 � punctuation
-%% 330 - 336 � - � uppercase
-%% 337 - 366 � - � lowercase
-%% 367 � punctuation
-%% 370 - 377 � - � lowercase
+%% 240 - 277 NBSP - ¿ punctuation
+%% 300 - 326 À - Ö uppercase
+%% 327 × punctuation
+%% 330 - 336 Ø - Þ uppercase
+%% 337 - 366 ß - ö lowercase
+%% 367 ÷ punctuation
+%% 370 - 377 ø - ÿ lowercase
%%
%% Many punctuation characters region have special meaning. Must
-%% watch using � \327, very close to x \170
+%% watch using × \327, very close to x \170
-module(io_lib).
-export([fwrite/2,fread/2,fread/3,format/2]).
-export([print/1,print/4,indentation/2]).
--export([write/1,write/2,write/3,nl/0,format_prompt/1]).
+-export([write/1,write/2,write/3,nl/0,format_prompt/1,format_prompt/2]).
-export([write_atom/1,write_string/1,write_string/2,write_unicode_string/1,
- write_unicode_string/2, write_char/1, write_unicode_char/1]).
+ write_unicode_string/2, write_char/1, write_unicode_char/1]).
+
+-export([write_unicode_string_as_latin1/1, write_unicode_string_as_latin1/2,
+ write_unicode_char_as_latin1/1]).
-export([quote_atom/2, char_list/1, unicode_char_list/1,
deep_char_list/1, deep_unicode_char_list/1,
@@ -75,11 +79,14 @@
collect_line/2, collect_line/3, collect_line/4,
get_until/3, get_until/4]).
--export_type([chars/0, continuation/0]).
+-export_type([chars/0, unicode_chars/0, unicode_string/0, continuation/0,
+ fread_error/0]).
%%----------------------------------------------------------------------
-type chars() :: [char() | chars()].
+-type unicode_chars() :: [unicode:unicode_char() | unicode_chars()].
+-type unicode_string() :: [unicode:unicode_char()].
-type depth() :: -1 | non_neg_integer().
-opaque continuation() :: {Format :: string(),
@@ -87,6 +94,16 @@
Nchars :: non_neg_integer(),
Results :: [term()]}.
+-type fread_error() :: 'atom'
+ | 'based'
+ | 'character'
+ | 'float'
+ | 'format'
+ | 'input'
+ | 'integer'
+ | 'string'
+ | 'unsigned'.
+
%%----------------------------------------------------------------------
%% Interface calls to sub-modules.
@@ -107,7 +124,7 @@ fwrite(Format, Args) ->
| {'more', RestFormat :: string(),
Nchars :: non_neg_integer(),
InputStack :: chars()}
- | {'error', What :: term()}.
+ | {'error', What :: fread_error()}.
fread(Chars, Format) ->
io_lib_fread:fread(Chars, Format).
@@ -120,7 +137,7 @@ fread(Chars, Format) ->
| {'done', Result, LeftOverChars :: string()},
Result :: {'ok', InputList :: [term()]}
| 'eof'
- | {'error', What :: term()}.
+ | {'error', What :: fread_error()}.
fread(Cont, Chars, Format) ->
io_lib_fread:fread(Cont, Chars, Format).
@@ -162,27 +179,34 @@ indentation(Chars, Current) ->
%% Format an IO-request prompt (handles formatting errors safely).
-%% Atoms, binaries, and iolists can be used as-is, and will be
-%% printed without any additional quotes.
-%% Note that the output is a deep string, and not an iolist (i.e.,
-%% it may be deep, but never contains binaries, due to the "~s").
+%% Atoms, binaries, and iolists (or unicode:charlist()) can be used
+%% as-is, and will be printed without any additional quotes.
-spec format_prompt(term()) -> chars().
-format_prompt({format,Format,Args}) ->
- format_prompt(Format,Args);
-format_prompt(Prompt)
- when is_list(Prompt); is_atom(Prompt); is_binary(Prompt) ->
- format_prompt("~ts", [Prompt]);
format_prompt(Prompt) ->
- format_prompt("~tp", [Prompt]).
+ format_prompt(Prompt, latin1).
+
+-spec format_prompt(term(), atom()) -> chars().
+
+format_prompt({format,Format,Args}, _Encoding) ->
+ do_format_prompt(Format, Args);
+format_prompt(Prompt, Encoding)
+ when is_list(Prompt); is_atom(Prompt); is_binary(Prompt) ->
+ do_format_prompt(add_modifier(Encoding, "s"), [Prompt]);
+format_prompt(Prompt, Encoding) ->
+ do_format_prompt(add_modifier(Encoding, "p"), [Prompt]).
-format_prompt(Format, Args) ->
+do_format_prompt(Format, Args) ->
case catch io_lib:format(Format, Args) of
{'EXIT',_} -> "???";
List -> List
end.
+add_modifier(latin1, C) ->
+ "~"++C;
+add_modifier(_, C) ->
+ "~t"++C.
%% write(Term)
%% write(Term, Depth)
@@ -294,7 +318,7 @@ quote_atom(Atom, Cs0) ->
case Cs0 of
[C|Cs] when C >= $a, C =< $z ->
not name_chars(Cs);
- [C|Cs] when C >= $�, C =< $�, C =/= $� ->
+ [C|Cs] when C >= $ß, C =< $ÿ, C =/= $÷ ->
not name_chars(Cs);
_ -> true
end
@@ -308,9 +332,9 @@ name_chars([C|Cs]) ->
name_chars([]) -> true.
name_char(C) when C >= $a, C =< $z -> true;
-name_char(C) when C >= $�, C =< $�, C =/= $� -> true;
+name_char(C) when C >= $ß, C =< $ÿ, C =/= $÷ -> true;
name_char(C) when C >= $A, C =< $Z -> true;
-name_char(C) when C >= $�, C =< $�, C =/= $� -> true;
+name_char(C) when C >= $À, C =< $Þ, C =/= $× -> true;
name_char(C) when C >= $0, C =< $9 -> true;
name_char($_) -> true;
name_char($@) -> true;
@@ -330,11 +354,32 @@ write_string(S) ->
write_string(S, Q) ->
[Q|write_string1(latin1, S, Q)].
+%%% There are two functions to write Unicode strings:
+%%% - they both escape control characters < 160;
+%%% - write_unicode_string() never escapes characters >= 160;
+%%% - write_unicode_string_as_latin1() also escapes characters >= 255.
+
+-spec write_unicode_string(UnicodeString) -> unicode_string() when
+ UnicodeString :: unicode_string().
+
write_unicode_string(S) ->
write_unicode_string(S, $"). %"
+-spec write_unicode_string(unicode_string(), char()) -> unicode_string().
+
write_unicode_string(S, Q) ->
- [Q|write_string1(unicode, S, Q)].
+ [Q|write_string1(unicode_as_unicode, S, Q)].
+
+-spec write_unicode_string_as_latin1(UnicodeString) -> string() when
+ UnicodeString :: unicode_string().
+
+write_unicode_string_as_latin1(S) ->
+ write_unicode_string_as_latin1(S, $"). %"
+
+-spec write_unicode_string_as_latin1(unicode_string(), char()) -> string().
+
+write_unicode_string_as_latin1(S, Q) ->
+ [Q|write_string1(unicode_as_latin1, S, Q)].
write_string1(_,[], Q) ->
[Q];
@@ -347,7 +392,11 @@ string_char(_,C, _, Tail) when C >= $\s, C =< $~ ->
[C|Tail];
string_char(latin1,C, _, Tail) when C >= $\240, C =< $\377 ->
[C|Tail];
-string_char(unicode,C, _, Tail) when C >= $\240 ->
+string_char(unicode_as_unicode,C, _, Tail) when C >= $\240 ->
+ [C|Tail];
+string_char(unicode_as_latin1,C, _, Tail) when C >= $\240, C =< $\377 ->
+ [C|Tail];
+string_char(unicode_as_latin1,C, _, Tail) when C >= $\377 ->
"\\x{"++erlang:integer_to_list(C, 16)++"}"++Tail;
string_char(_,$\n, _, Tail) -> [$\\,$n|Tail]; %\n = LF
string_char(_,$\r, _, Tail) -> [$\\,$r|Tail]; %\r = CR
@@ -374,10 +423,22 @@ write_char($\s) -> "$\\s"; %Must special case this.
write_char(C) when is_integer(C), C >= $\000, C =< $\377 ->
[$$|string_char(latin1,C, -1, [])].
-write_unicode_char(Ch) when Ch =< 255 ->
- write_char(Ch);
-write_unicode_char(Uni) ->
- [$$|string_char(unicode,Uni, -1, [])].
+%%% There are two functions to write a Unicode character:
+%%% - they both escape control characters < 160;
+%%% - write_unicode_char() never escapes characters >= 160;
+%%% - write_unicode_char_as_latin1() also escapes characters >= 255.
+
+-spec write_unicode_char(UnicodeChar) -> unicode_string() when
+ UnicodeChar :: unicode:unicode_char().
+
+write_unicode_char(Uni) when is_integer(Uni), Uni >= $\000 ->
+ [$$|string_char(unicode_as_unicode,Uni, -1, [])].
+
+-spec write_unicode_char_as_latin1(UnicodeChar) -> string() when
+ UnicodeChar :: unicode:unicode_char().
+
+write_unicode_char_as_latin1(Uni) when is_integer(Uni), Uni >= $\000 ->
+ [$$|string_char(unicode_as_latin1,Uni, -1, [])].
%% char_list(CharList)
%% deep_char_list(CharList)
@@ -392,7 +453,8 @@ char_list([C|Cs]) when is_integer(C), C >= $\000, C =< $\377 ->
char_list([]) -> true;
char_list(_) -> false. %Everything else is false
--spec unicode_char_list(term()) -> boolean().
+-spec unicode_char_list(Term) -> boolean() when
+ Term :: term().
unicode_char_list([C|Cs]) when is_integer(C), C >= 0, C < 16#D800;
is_integer(C), C > 16#DFFF, C < 16#FFFE;
@@ -417,7 +479,8 @@ deep_char_list([], []) -> true;
deep_char_list(_, _More) -> %Everything else is false
false.
--spec deep_unicode_char_list(term()) -> boolean().
+-spec deep_unicode_char_list(Term) -> boolean() when
+ Term :: term().
deep_unicode_char_list(Cs) ->
deep_unicode_char_list(Cs, []).
@@ -462,7 +525,8 @@ printable_list(_) -> false. %Everything else is false
%% Everything that is not a control character and not invalid unicode
%% will be considered printable.
--spec printable_unicode_list(term()) -> boolean().
+-spec printable_unicode_list(Term) -> boolean() when
+ Term :: term().
printable_unicode_list([C|Cs]) when is_integer(C), C >= $\040, C =< $\176 ->
printable_unicode_list(Cs);
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index 49a00a4ec7..5680f83ab6 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,7 +22,7 @@
-export([fwrite/2,fwrite_g/1,indentation/2]).
-%% fwrite(Format, ArgList) -> [Char].
+%% fwrite(Format, ArgList) -> [unicode:unicode:char()].
%% Format the arguments in ArgList after string Format. Just generate
%% an error if there is an error in the arguments.
%%
@@ -133,7 +133,7 @@ pcount([{$P,_As,_F,_Ad,_P,_Pad,_Enc}|Cs], Acc) -> pcount(Cs, Acc+1);
pcount([_|Cs], Acc) -> pcount(Cs, Acc);
pcount([], Acc) -> Acc.
-%% build([Control], Pc, Indentation) -> [Char].
+%% build([Control], Pc, Indentation) -> [unicode:unicode_char()].
%% Interpret the control structures. Count the number of print
%% remaining and only calculate indentation when necessary. Must also
%% be smart when calculating indentation for characters in format.
@@ -154,7 +154,7 @@ decr_pc($p, Pc) -> Pc - 1;
decr_pc($P, Pc) -> Pc - 1;
decr_pc(_, Pc) -> Pc.
-%% indentation([Char], Indentation) -> Indentation.
+%% indentation([unicode:unicode_char()], Indentation) -> Indentation.
%% Calculate the indentation of the end of a string given its start
%% indentation. We assume tabs at 8 cols.
@@ -167,19 +167,19 @@ indentation([C|Cs], I) ->
indentation([], I) -> I.
%% control(FormatChar, [Argument], FieldWidth, Adjust, Precision, PadChar,
-%% Indentation) ->
-%% [Char]
+%% Encoding, Indentation) ->
+%% [unicode:unicode_char()]
%% This is the main dispatch function for the various formatting commands.
%% Field widths and precisions have already been calculated.
control($w, [A], F, Adj, P, Pad, _Enc,_I) ->
term(io_lib:write(A, -1), F, Adj, P, Pad);
-control($p, [A], F, Adj, P, Pad, _Enc, I) ->
- print(A, -1, F, Adj, P, Pad, I);
+control($p, [A], F, Adj, P, Pad, Enc, I) ->
+ print(A, -1, F, Adj, P, Pad, Enc, I);
control($W, [A,Depth], F, Adj, P, Pad, _Enc, _I) when is_integer(Depth) ->
term(io_lib:write(A, Depth), F, Adj, P, Pad);
-control($P, [A,Depth], F, Adj, P, Pad, _Enc, I) when is_integer(Depth) ->
- print(A, Depth, F, Adj, P, Pad, I);
+control($P, [A,Depth], F, Adj, P, Pad, Enc, I) when is_integer(Depth) ->
+ print(A, Depth, F, Adj, P, Pad, Enc, I);
control($s, [A], F, Adj, P, Pad, _Enc, _I) when is_atom(A) ->
string(atom_to_list(A), F, Adj, P, Pad);
control($s, [L0], F, Adj, P, Pad, latin1, _I) ->
@@ -187,6 +187,7 @@ control($s, [L0], F, Adj, P, Pad, latin1, _I) ->
string(L, F, Adj, P, Pad);
control($s, [L0], F, Adj, P, Pad, unicode, _I) ->
L = unicode:characters_to_list(L0),
+ true = is_list(L),
uniconv(string(L, F, Adj, P, Pad));
control($e, [A], F, Adj, P, Pad, _Enc, _I) when is_float(A) ->
fwrite_e(A, F, Adj, P, Pad);
@@ -256,13 +257,17 @@ term(T, F, Adj, P0, Pad) ->
adjust(T, chars(Pad, F-L), Adj)
end.
-%% print(Term, Depth, Field, Adjust, Precision, PadChar, Indentation)
+%% print(Term, Depth, Field, Adjust, Precision, PadChar, Encoding,
+%% Indentation)
%% Print a term.
-print(T, D, none, Adj, P, Pad, I) -> print(T, D, 80, Adj, P, Pad, I);
-print(T, D, F, Adj, none, Pad, I) -> print(T, D, F, Adj, I+1, Pad, I);
-print(T, D, F, right, P, _Pad, _I) ->
- io_lib_pretty:print(T, P, F, D).
+print(T, D, none, Adj, P, Pad, E, I) -> print(T, D, 80, Adj, P, Pad, E, I);
+print(T, D, F, Adj, none, Pad, E, I) -> print(T, D, F, Adj, I+1, Pad, E, I);
+print(T, D, F, right, P, _Pad, latin1, _I) ->
+ io_lib_pretty:print(T, P, F, D);
+print(T, D, F, right, P, _Pad, Enc, _I) ->
+ Options = [{column, P}, {line_length, F}, {depth, D}, {encoding, Enc}],
+ io_lib_pretty:print(T, Options).
%% fwrite_e(Float, Field, Adjust, Precision, PadChar)
@@ -608,7 +613,7 @@ prefixed_integer(Int, F, Adj, Base, Pad, Prefix, Lowercase)
term([Prefix|S], F, Adj, none, Pad)
end.
-%% char(Char, Field, Adjust, Precision, PadChar) -> [Char].
+%% char(Char, Field, Adjust, Precision, PadChar) -> [unicode:unicode_char()].
char(C, none, _Adj, none, _Pad) -> [C];
char(C, F, _Adj, none, _Pad) -> chars(C, F);
diff --git a/lib/stdlib/src/io_lib_fread.erl b/lib/stdlib/src/io_lib_fread.erl
index ded1346097..84d4b8bba0 100644
--- a/lib/stdlib/src/io_lib_fread.erl
+++ b/lib/stdlib/src/io_lib_fread.erl
@@ -43,7 +43,7 @@
| {'done', Result, LeftOverChars :: string()},
Result :: {'ok', InputList :: io_lib:chars()}
| 'eof'
- | {'error', What :: term()}.
+ | {'error', What :: io_lib:fread_error()}.
fread([], Chars, Format) ->
%%io:format("FREAD: ~w `~s'~n", [Format,Chars]),
diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl
index 169410796b..99ad281a9b 100644
--- a/lib/stdlib/src/io_lib_pretty.erl
+++ b/lib/stdlib/src/io_lib_pretty.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -33,43 +33,76 @@
%% print(Term, Column, LineLength, Depth) -> [Chars]
%% Depth = -1 gives unlimited print depth. Use io_lib:write for atomic terms.
+-spec print(term()) -> io_lib:chars().
+
print(Term) ->
print(Term, 1, 80, -1).
%% print(Term, RecDefFun) -> [Chars]
%% print(Term, Depth, RecDefFun) -> [Chars]
%% RecDefFun = fun(Tag, NoFields) -> [FieldTag] | no
-%% Used by the shell for printing records.
+%% Used by the shell for printing records and for Unicode.
+
+-type rec_print_fun() :: fun((Tag :: atom(), NFields :: non_neg_integer()) ->
+ no | [FieldName :: atom()]).
+-type column() :: integer().
+-type line_length() :: pos_integer().
+-type depth() :: integer().
+-type max_chars() :: integer().
+
+-type chars() :: io_lib:chars().
+-type unicode_chars() :: io_lib:unicode_chars().
+-type option() :: {column, column()}
+ | {line_length, line_length()}
+ | {depth, depth()}
+ | {max_chars, max_chars()}
+ | {record_print_fun, rec_print_fun()}
+ | {encoding, latin1 | utf8 | unicode}.
+-type options() :: [option()].
+
+-spec print(term(), rec_print_fun()) -> chars() | unicode_chars();
+ (term(), options()) -> chars() | unicode_chars().
+
+print(Term, Options) when is_list(Options) ->
+ Col = proplists:get_value(column, Options, 1),
+ Ll = proplists:get_value(line_length, Options, 80),
+ D = proplists:get_value(depth, Options, -1),
+ M = proplists:get_value(max_chars, Options, -1),
+ RecDefFun = proplists:get_value(record_print_fun, Options, no_fun),
+ Encoding = proplists:get_value(encoding, Options, epp:default_encoding()),
+ print(Term, Col, Ll, D, M, RecDefFun, Encoding);
print(Term, RecDefFun) ->
print(Term, -1, RecDefFun).
+-spec print(term(), depth(), rec_print_fun()) -> chars() | unicode_chars().
+
print(Term, Depth, RecDefFun) ->
print(Term, 1, 80, Depth, RecDefFun).
+-spec print(term(), column(), line_length(), depth()) ->
+ chars() | unicode_chars().
+
print(Term, Col, Ll, D) ->
- print(Term, Col, Ll, D, _M=-1, no_fun).
+ print(Term, Col, Ll, D, _M=-1, no_fun, latin1).
+-spec print(term(), column(), line_length(), depth(), rec_print_fun()) ->
+ chars() | unicode_chars().
print(Term, Col, Ll, D, RecDefFun) ->
print(Term, Col, Ll, D, _M=-1, RecDefFun).
-print(_, _, _, 0, _M, _RF) -> "...";
-print(Term, Col, Ll, D, M, RecDefFun) when Col =< 0 ->
- print(Term, 1, Ll, D, M, RecDefFun);
-print(Term, Col, Ll, D, M0, RecDefFun) when is_tuple(Term);
- is_list(Term) ->
- If = {_S, Len} = print_length(Term, D, RecDefFun),
- M = max_cs(M0, Len),
- if
- Len < Ll - Col, Len =< M ->
- write(If);
- true ->
- TInd = while_fail([-1, 4],
- fun(I) -> cind(If, Col, Ll, M, I, 0, 0) end,
- 1),
- pp(If, Col, Ll, M, TInd, indent(Col), 0, 0)
- end;
-print(<<_/bitstring>>=Term, Col, Ll, D, M0, RecDefFun) ->
- If = {_S, Len} = print_length(Term, D, RecDefFun),
+-spec print(term(), column(), line_length(), depth(), max_chars(),
+ rec_print_fun()) -> chars() | unicode_chars().
+
+print(Term, Col, Ll, D, M, RecDefFun) ->
+ print(Term, Col, Ll, D, M, RecDefFun, latin1).
+
+print(_, _, _, 0, _M, _RF, _Enc) -> "...";
+print(Term, Col, Ll, D, M, RecDefFun, Enc) when Col =< 0 ->
+ print(Term, 1, Ll, D, M, RecDefFun, Enc);
+print(Term, Col, Ll, D, M0, RecDefFun, Enc) when is_tuple(Term);
+ is_list(Term);
+ is_bitstring(Term) ->
+ If = {_S, Len} = print_length(Term, D, RecDefFun, Enc),
M = max_cs(M0, Len),
if
Len < Ll - Col, Len =< M ->
@@ -80,7 +113,7 @@ print(<<_/bitstring>>=Term, Col, Ll, D, M0, RecDefFun) ->
1),
pp(If, Col, Ll, M, TInd, indent(Col), 0, 0)
end;
-print(Term, _Col, _Ll, _D, _M, _RF) ->
+print(Term, _Col, _Ll, _D, _M, _RF, _Enc) ->
io_lib:write(Term).
%%%
@@ -294,50 +327,56 @@ write_tail(E, S) ->
%% counted but need to be added later.
%% D =/= 0
-print_length([], _D, _RF) ->
+print_length([], _D, _RF, _Enc) ->
{"[]", 2};
-print_length({}, _D, _RF) ->
+print_length({}, _D, _RF, _Enc) ->
{"{}", 2};
-print_length(List, D, RF) when is_list(List) ->
- case printable_list(List, D) of
+print_length(List, D, RF, Enc) when is_list(List) ->
+ case printable_list(List, D, Enc) of
true ->
- S = io_lib:write_string(List, $"), %"
+ S = write_string(List, Enc),
{S, length(S)};
%% Truncated lists could break some existing code.
% {true, Prefix} ->
- % S = io_lib:write_string(Prefix, $"), %"
+ % S = write_string(Prefix, Enc),
% {[S | "..."], 3 + length(S)};
false ->
- print_length_list(List, D, RF)
+ print_length_list(List, D, RF, Enc)
end;
-print_length(Fun, _D, _RF) when is_function(Fun) ->
+print_length(Fun, _D, _RF, _Enc) when is_function(Fun) ->
S = io_lib:write(Fun),
{S, iolist_size(S)};
-print_length(R, D, RF) when is_atom(element(1, R)),
- is_function(RF) ->
+print_length(R, D, RF, Enc) when is_atom(element(1, R)),
+ is_function(RF) ->
case RF(element(1, R), tuple_size(R) - 1) of
no ->
- print_length_tuple(R, D, RF);
+ print_length_tuple(R, D, RF, Enc);
RDefs ->
- print_length_record(R, D, RF, RDefs)
+ print_length_record(R, D, RF, RDefs, Enc)
end;
-print_length(Tuple, D, RF) when is_tuple(Tuple) ->
- print_length_tuple(Tuple, D, RF);
-print_length(<<>>, _D, _RF) ->
+print_length(Tuple, D, RF, Enc) when is_tuple(Tuple) ->
+ print_length_tuple(Tuple, D, RF, Enc);
+print_length(<<>>, _D, _RF, _Enc) ->
{"<<>>", 4};
-print_length(<<_/bitstring>>, 1, _RF) ->
+print_length(<<_/bitstring>>, 1, _RF, _Enc) ->
{"<<...>>", 7};
-print_length(<<_/bitstring>>=Bin, D, _RF) ->
+print_length(<<_/bitstring>>=Bin, D, _RF, Enc) ->
case bit_size(Bin) rem 8 of
0 ->
D1 = D - 1,
- case printable_bin(Bin, D1) of
- List when is_list(List) ->
- S = io_lib:write_string(List, $"),
+ case printable_bin(Bin, D1, Enc) of
+ {true, List} when is_list(List) ->
+ S = io_lib:write_string(List, $"), %"
{[$<,$<,S,$>,$>], 4 + length(S)};
- {true, Prefix} ->
- S = io_lib:write_string(Prefix, $"),
- {[$<,$<, S | "...>>"], 4 + length(S)};
+ {false, List} when is_list(List) ->
+ S = io_lib:write_unicode_string(List, $"), %"
+ {[$<,$<,S,"/utf8>>"], 9 + length(S)};
+ {true, true, Prefix} ->
+ S = io_lib:write_string(Prefix, $"), %"
+ {[$<,$<, S | "...>>"], 7 + length(S)};
+ {false, true, Prefix} ->
+ S = io_lib:write_unicode_string(Prefix, $"), %"
+ {[$<,$<, S | "/utf8...>>"], 12 + length(S)};
false ->
S = io_lib:write(Bin, D),
{{bin,S}, iolist_size(S)}
@@ -346,51 +385,51 @@ print_length(<<_/bitstring>>=Bin, D, _RF) ->
S = io_lib:write(Bin, D),
{{bin,S}, iolist_size(S)}
end;
-print_length(Term, _D, _RF) ->
+print_length(Term, _D, _RF, _Enc) ->
S = io_lib:write(Term),
{S, iolist_size(S)}.
-print_length_tuple(_Tuple, 1, _RF) ->
+print_length_tuple(_Tuple, 1, _RF, _Enc) ->
{"{...}", 5};
-print_length_tuple(Tuple, D, RF) ->
- L = print_length_list1(tuple_to_list(Tuple), D, RF),
+print_length_tuple(Tuple, D, RF, Enc) ->
+ L = print_length_list1(tuple_to_list(Tuple), D, RF, Enc),
IsTagged = is_atom(element(1, Tuple)) and (tuple_size(Tuple) > 1),
{{tuple,IsTagged,L}, list_length(L, 2)}.
-print_length_record(_Tuple, 1, _RF, _RDefs) ->
+print_length_record(_Tuple, 1, _RF, _RDefs, _Enc) ->
{"{...}", 5};
-print_length_record(Tuple, D, RF, RDefs) ->
+print_length_record(Tuple, D, RF, RDefs, Enc) ->
Name = [$# | io_lib:write_atom(element(1, Tuple))],
NameL = length(Name),
- L = print_length_fields(RDefs, D - 1, tl(tuple_to_list(Tuple)), RF),
+ L = print_length_fields(RDefs, D - 1, tl(tuple_to_list(Tuple)), RF, Enc),
{{record, [{Name,NameL} | L]}, list_length(L, NameL + 2)}.
-print_length_fields([], _D, [], _RF) ->
+print_length_fields([], _D, [], _RF, _Enc) ->
[];
-print_length_fields(_, 1, _, _RF) ->
+print_length_fields(_, 1, _, _RF, _Enc) ->
{dots, 3};
-print_length_fields([Def | Defs], D, [E | Es], RF) ->
- [print_length_field(Def, D - 1, E, RF) |
- print_length_fields(Defs, D - 1, Es, RF)].
+print_length_fields([Def | Defs], D, [E | Es], RF, Enc) ->
+ [print_length_field(Def, D - 1, E, RF, Enc) |
+ print_length_fields(Defs, D - 1, Es, RF, Enc)].
-print_length_field(Def, D, E, RF) ->
+print_length_field(Def, D, E, RF, Enc) ->
Name = io_lib:write_atom(Def),
- {S, L} = print_length(E, D, RF),
+ {S, L} = print_length(E, D, RF, Enc),
NameL = length(Name) + 3,
{{field, Name, NameL, {S, L}}, NameL + L}.
-print_length_list(List, D, RF) ->
- L = print_length_list1(List, D, RF),
+print_length_list(List, D, RF, Enc) ->
+ L = print_length_list1(List, D, RF, Enc),
{{list, L}, list_length(L, 2)}.
-print_length_list1([], _D, _RF) ->
+print_length_list1([], _D, _RF, _Enc) ->
[];
-print_length_list1(_, 1, _RF) ->
+print_length_list1(_, 1, _RF, _Enc) ->
{dots, 3};
-print_length_list1([E | Es], D, RF) ->
- [print_length(E, D - 1, RF) | print_length_list1(Es, D - 1, RF)];
-print_length_list1(E, D, RF) ->
- print_length(E, D - 1, RF).
+print_length_list1([E | Es], D, RF, Enc) ->
+ [print_length(E, D - 1, RF, Enc) | print_length_list1(Es, D - 1, RF, Enc)];
+print_length_list1(E, D, RF, Enc) ->
+ print_length(E, D - 1, RF, Enc).
list_length([], Acc) ->
Acc;
@@ -409,16 +448,16 @@ list_length_tail({_, Len}, Acc) ->
%% ?CHARS printable characters has depth 1.
-define(CHARS, 4).
-printable_list(L, D) when D < 0 ->
- io_lib:printable_list(L);
-printable_list(_L, 1) ->
+printable_list(_L, 1, _Enc) ->
false;
-printable_list(L, _D) ->
- io_lib:printable_list(L).
+printable_list(L, _D, latin1) ->
+ io_lib:printable_list(L);
+printable_list(L, _D, _Uni) ->
+ io_lib:printable_unicode_list(L).
%% Truncated lists could break some existing code.
-% printable_list(L, D) ->
+% printable_list(L, D, Enc) when D >= 0 ->
% Len = ?CHARS * (D - 1),
-% case printable_list1(L, Len) of
+% case printable_list1(L, Len, Enc) of
% all ->
% true;
% N when is_integer(N), Len - N >= D - 1 ->
@@ -428,32 +467,41 @@ printable_list(L, _D) ->
% false
% end.
-printable_bin(Bin, D) when D >= 0, ?CHARS * D =< byte_size(Bin) ->
- printable_bin(Bin, erlang:min(?CHARS * D, byte_size(Bin)), D);
-printable_bin(Bin, D) ->
- printable_bin(Bin, byte_size(Bin), D).
+printable_bin(Bin, D, Enc) when D >= 0, ?CHARS * D =< byte_size(Bin) ->
+ printable_bin(Bin, erlang:min(?CHARS * D, byte_size(Bin)), D, Enc);
+printable_bin(Bin, D, Enc) ->
+ printable_bin(Bin, byte_size(Bin), D, Enc).
-printable_bin(Bin, Len, D) ->
+printable_bin(Bin, Len, D, latin1) ->
N = erlang:min(20, Len),
L = binary_to_list(Bin, 1, N),
case printable_list1(L, N) of
all when N =:= byte_size(Bin) ->
- L;
- all when N =:= Len -> % N < byte_size(Bin)
{true, L};
+ all when N =:= Len -> % N < byte_size(Bin)
+ {true, true, L};
all ->
case printable_bin1(Bin, 1 + N, Len - N) of
0 when byte_size(Bin) =:= Len ->
- binary_to_list(Bin);
+ {true, binary_to_list(Bin)};
NC when D > 0, Len - NC >= D ->
- {true, binary_to_list(Bin, 1, Len - NC)};
+ {true, true, binary_to_list(Bin, 1, Len - NC)};
NC when is_integer(NC) ->
false
end;
NC when is_integer(NC), D > 0, N - NC >= D ->
- {true, binary_to_list(Bin, 1, N - NC)};
+ {true, true, binary_to_list(Bin, 1, N - NC)};
NC when is_integer(NC) ->
false
+ end;
+printable_bin(Bin, Len, D, _Uni) ->
+ case printable_unicode(Bin, Len, []) of
+ {_, <<>>, L} ->
+ {byte_size(Bin) =:= length(L), L};
+ {NC, Bin1, L} when D > 0, Len - NC >= D ->
+ {byte_size(Bin)-byte_size(Bin1) =:= length(L), true, L};
+ {_NC, _Bin, _L} ->
+ false
end.
printable_bin1(_Bin, _Start, 0) ->
@@ -484,6 +532,16 @@ printable_list1([$\e | Cs], N) -> printable_list1(Cs, N - 1);
printable_list1([], _) -> all;
printable_list1(_, N) -> N.
+printable_unicode(<<C/utf8, R/binary>>, I, L) when I > 0 ->
+ printable_unicode(R, I - 1, [C | L]);
+printable_unicode(Bin, I, L) ->
+ {I, Bin, lists:reverse(L)}.
+
+write_string(S, latin1) ->
+ io_lib:write_string(S, $"); %"
+write_string(S, _Uni) ->
+ io_lib:write_unicode_string(S, $"). %"
+
%% Throw 'no_good' if the indentation exceeds half the line length
%% unless there is room for M characters on the line.
diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl
index cf4b87d7eb..b2ce2a5a8f 100644
--- a/lib/stdlib/src/lib.erl
+++ b/lib/stdlib/src/lib.erl
@@ -21,8 +21,9 @@
-export([flush_receive/0, error_message/2, progname/0, nonl/1, send/2,
sendw/2, eval_str/1]).
--export([format_exception/6, format_stacktrace/4,
- format_call/4, format_fun/1]).
+-export([format_exception/6, format_exception/7,
+ format_stacktrace/4, format_stacktrace/5,
+ format_call/4, format_call/5, format_fun/1]).
-spec flush_receive() -> 'ok'.
@@ -128,32 +129,49 @@ all_white(_) -> false.
%% as indentation whenever newline has been inserted);
%% Class, Reason and StackTrace are the exception;
%% FormatFun = fun(Term, I) -> iolist() formats terms;
-%% StackFun = fun(Mod, Fun, Arity) -> bool() is used for trimming the
+%% StackFun = fun(Mod, Fun, Arity) -> boolean() is used for trimming the
%% end of the stack (typically calls to erl_eval are skipped).
-format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun)
+format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun) ->
+ format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun,
+ latin1).
+
+%% -> iolist() | unicode:charlist() (no \n at end)
+%% FormatFun = fun(Term, I) -> iolist() | unicode:charlist().
+format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun, Encoding)
when is_integer(I), I >= 1, is_function(StackFun, 3),
is_function(FormatFun, 2) ->
S = n_spaces(I-1),
{Term,Trace1,Trace} = analyze_exception(Class, Reason, StackTrace),
- Expl0 = explain_reason(Term, Class, Trace1, FormatFun, S),
- Expl = io_lib:fwrite(<<"~s~s">>, [exited(Class), Expl0]),
- case format_stacktrace1(S, Trace, FormatFun, StackFun) of
+ Expl0 = explain_reason(Term, Class, Trace1, FormatFun, S, Encoding),
+ FormatString = case Encoding of
+ latin1 -> "~s~s";
+ _ -> "~s~ts"
+ end,
+ Expl = io_lib:fwrite(FormatString, [exited(Class), Expl0]),
+ case format_stacktrace1(S, Trace, FormatFun, StackFun, Encoding) of
[] -> Expl;
Stack -> [Expl, $\n, Stack]
end.
%% -> iolist() (no \n at end)
-format_stacktrace(I, StackTrace, StackFun, FormatFun)
+format_stacktrace(I, StackTrace, StackFun, FormatFun) ->
+ format_stacktrace(I, StackTrace, StackFun, FormatFun, latin1).
+
+%% -> iolist() | unicode:charlist() (no \n at end)
+format_stacktrace(I, StackTrace, StackFun, FormatFun, Encoding)
when is_integer(I), I >= 1, is_function(StackFun, 3),
is_function(FormatFun, 2) ->
S = n_spaces(I-1),
- format_stacktrace1(S, StackTrace, FormatFun, StackFun).
+ format_stacktrace1(S, StackTrace, FormatFun, StackFun, Encoding).
%% -> iolist() (no \n at end)
-format_call(I, ForMForFun, As, FormatFun) when is_integer(I), I >= 1,
- is_list(As),
- is_function(FormatFun, 2) ->
- format_call("", n_spaces(I-1), ForMForFun, As, FormatFun).
+format_call(I, ForMForFun, As, FormatFun) ->
+ format_call(I, ForMForFun, As, FormatFun, latin1).
+
+%% -> iolist() | unicode:charlist() (no \n at end)
+format_call(I, ForMForFun, As, FormatFun, Enc)
+ when is_integer(I), I >= 1, is_list(As), is_function(FormatFun, 2) ->
+ format_call("", n_spaces(I-1), ForMForFun, As, FormatFun, Enc).
%% -> iolist() (no \n at end)
format_fun(Fun) when is_function(Fun) ->
@@ -204,79 +222,80 @@ is_stacktrace(_) ->
false.
%% ERTS exit codes (some of them are also returned by erl_eval):
-explain_reason(badarg, error, [], _PF, _S) ->
+explain_reason(badarg, error, [], _PF, _S, _Enc) ->
<<"bad argument">>;
-explain_reason({badarg,V}, error=Cl, [], PF, S) -> % orelse, andalso
+explain_reason({badarg,V}, error=Cl, [], PF, S, _Enc) -> % orelse, andalso
format_value(V, <<"bad argument: ">>, Cl, PF, S);
-explain_reason(badarith, error, [], _PF, _S) ->
+explain_reason(badarith, error, [], _PF, _S, _Enc) ->
<<"an error occurred when evaluating an arithmetic expression">>;
-explain_reason({badarity,{Fun,As}}, error, [], _PF, _S)
+explain_reason({badarity,{Fun,As}}, error, [], _PF, _S, _Enc)
when is_function(Fun) ->
%% Only the arity is displayed, not the arguments As.
io_lib:fwrite(<<"~s called with ~s">>,
[format_fun(Fun), argss(length(As))]);
-explain_reason({badfun,Term}, error=Cl, [], PF, S) ->
+explain_reason({badfun,Term}, error=Cl, [], PF, S, _Enc) ->
format_value(Term, <<"bad function ">>, Cl, PF, S);
-explain_reason({badmatch,Term}, error=Cl, [], PF, S) ->
- format_value(Term, <<"no match of right hand side value ">>, Cl, PF, S);
-explain_reason({case_clause,V}, error=Cl, [], PF, S) ->
+explain_reason({badmatch,Term}, error=Cl, [], PF, S, _Enc) ->
+ Str = <<"no match of right hand side value ">>,
+ format_value(Term, Str, Cl, PF, S);
+explain_reason({case_clause,V}, error=Cl, [], PF, S, _Enc) ->
%% "there is no case clause with a true guard sequence and a
%% pattern matching..."
format_value(V, <<"no case clause matching ">>, Cl, PF, S);
-explain_reason(function_clause, error, [{F,A}], _PF, _S) ->
+explain_reason(function_clause, error, [{F,A}], _PF, _S, _Enc) ->
%% Shell commands
FAs = io_lib:fwrite(<<"~w/~w">>, [F, A]),
[<<"no function clause matching call to ">> | FAs];
-explain_reason(function_clause, error=Cl, [{M,F,As,Loc}], PF, S) ->
+explain_reason(function_clause, error=Cl, [{M,F,As,Loc}], PF, S, Enc) ->
Str = <<"no function clause matching ">>,
- [format_errstr_call(Str, Cl, {M,F}, As, PF, S),$\s|location(Loc)];
-explain_reason(if_clause, error, [], _PF, _S) ->
+ [format_errstr_call(Str, Cl, {M,F}, As, PF, S, Enc),$\s|location(Loc)];
+explain_reason(if_clause, error, [], _PF, _S, _Enc) ->
<<"no true branch found when evaluating an if expression">>;
-explain_reason(noproc, error, [], _PF, _S) ->
+explain_reason(noproc, error, [], _PF, _S, _Enc) ->
<<"no such process or port">>;
-explain_reason(notalive, error, [], _PF, _S) ->
+explain_reason(notalive, error, [], _PF, _S, _Enc) ->
<<"the node cannot be part of a distributed system">>;
-explain_reason(system_limit, error, [], _PF, _S) ->
+explain_reason(system_limit, error, [], _PF, _S, _Enc) ->
<<"a system limit has been reached">>;
-explain_reason(timeout_value, error, [], _PF, _S) ->
+explain_reason(timeout_value, error, [], _PF, _S, _Enc) ->
<<"bad receive timeout value">>;
-explain_reason({try_clause,V}, error=Cl, [], PF, S) ->
+explain_reason({try_clause,V}, error=Cl, [], PF, S, _Enc) ->
%% "there is no try clause with a true guard sequence and a
%% pattern matching..."
format_value(V, <<"no try clause matching ">>, Cl, PF, S);
-explain_reason(undef, error, [{M,F,A,_}], _PF, _S) ->
+explain_reason(undef, error, [{M,F,A,_}], _PF, _S, _Enc) ->
%% Only the arity is displayed, not the arguments, if there are any.
io_lib:fwrite(<<"undefined function ~s">>,
[mfa_to_string(M, F, n_args(A))]);
-explain_reason({shell_undef,F,A,_}, error, [], _PF, _S) ->
+explain_reason({shell_undef,F,A,_}, error, [], _PF, _S, _Enc) ->
%% Give nicer reports for undefined shell functions
%% (but not when the user actively calls shell_default:F(...)).
io_lib:fwrite(<<"undefined shell command ~s/~w">>, [F, n_args(A)]);
%% Exit codes returned by erl_eval only:
-explain_reason({argument_limit,_Fun}, error, [], _PF, _S) ->
+explain_reason({argument_limit,_Fun}, error, [], _PF, _S, _Enc) ->
io_lib:fwrite(<<"limit of number of arguments to interpreted function"
" exceeded">>, []);
-explain_reason({bad_filter,V}, error=Cl, [], PF, S) ->
+explain_reason({bad_filter,V}, error=Cl, [], PF, S, _Enc) ->
format_value(V, <<"bad filter ">>, Cl, PF, S);
-explain_reason({bad_generator,V}, error=Cl, [], PF, S) ->
+explain_reason({bad_generator,V}, error=Cl, [], PF, S, _Enc) ->
format_value(V, <<"bad generator ">>, Cl, PF, S);
-explain_reason({unbound,V}, error, [], _PF, _S) ->
+explain_reason({unbound,V}, error, [], _PF, _S, _Enc) ->
io_lib:fwrite(<<"variable ~w is unbound">>, [V]);
%% Exit codes local to the shell module (restricted shell):
-explain_reason({restricted_shell_bad_return, V}, exit=Cl, [], PF, S) ->
+explain_reason({restricted_shell_bad_return, V}, exit=Cl, [], PF, S, _Enc) ->
Str = <<"restricted shell module returned bad value ">>,
format_value(V, Str, Cl, PF, S);
explain_reason({restricted_shell_disallowed,{ForMF,As}},
- exit=Cl, [], PF, S) ->
+ exit=Cl, [], PF, S, Enc) ->
%% ForMF can be a fun, but not a shell fun.
Str = <<"restricted shell does not allow ">>,
- format_errstr_call(Str, Cl, ForMF, As, PF, S);
-explain_reason(restricted_shell_started, exit, [], _PF, _S) ->
+ format_errstr_call(Str, Cl, ForMF, As, PF, S, Enc);
+explain_reason(restricted_shell_started, exit, [], _PF, _S, _Enc) ->
<<"restricted shell starts now">>;
-explain_reason(restricted_shell_stopped, exit, [], _PF, _S) ->
+explain_reason(restricted_shell_stopped, exit, [], _PF, _S, _Enc) ->
<<"restricted shell stopped">>;
%% Other exit code:
-explain_reason(Reason, Class, [], PF, S) ->
+explain_reason(Reason, Class, [], PF, S, _Enc) ->
PF(Reason, (iolist_size(S)+1) + exited_size(Class)).
n_args(A) when is_integer(A) ->
@@ -293,28 +312,28 @@ argss(2) ->
argss(I) ->
io_lib:fwrite(<<"~w arguments">>, [I]).
-format_stacktrace1(S0, Stack0, PF, SF) ->
+format_stacktrace1(S0, Stack0, PF, SF, Enc) ->
Stack1 = lists:dropwhile(fun({M,F,A,_}) -> SF(M, F, A)
end, lists:reverse(Stack0)),
S = [" " | S0],
Stack = lists:reverse(Stack1),
- format_stacktrace2(S, Stack, 1, PF).
+ format_stacktrace2(S, Stack, 1, PF, Enc).
-format_stacktrace2(S, [{M,F,A,L}|Fs], N, PF) when is_integer(A) ->
+format_stacktrace2(S, [{M,F,A,L}|Fs], N, PF, Enc) when is_integer(A) ->
[io_lib:fwrite(<<"~s~s ~s ~s">>,
[sep(N, S), origin(N, M, F, A),
mfa_to_string(M, F, A),
location(L)])
- | format_stacktrace2(S, Fs, N + 1, PF)];
-format_stacktrace2(S, [{M,F,As,_}|Fs], N, PF) when is_list(As) ->
+ | format_stacktrace2(S, Fs, N + 1, PF, Enc)];
+format_stacktrace2(S, [{M,F,As,_}|Fs], N, PF, Enc) when is_list(As) ->
A = length(As),
CalledAs = [S,<<" called as ">>],
- C = format_call("", CalledAs, {M,F}, As, PF),
- [io_lib:fwrite(<<"~s~s ~s\n~s~s">>,
+ C = format_call("", CalledAs, {M,F}, As, PF, Enc),
+ [io_lib:fwrite(<<"~s~s ~s\n~s~ts">>,
[sep(N, S), origin(N, M, F, A), mfa_to_string(M, F, A),
CalledAs, C])
- | format_stacktrace2(S, Fs, N + 1, PF)];
-format_stacktrace2(_S, [], _N, _PF) ->
+ | format_stacktrace2(S, Fs, N + 1, PF, Enc)];
+format_stacktrace2(_S, [], _N, _PF, _Enc) ->
"".
location(L) ->
@@ -338,22 +357,22 @@ origin(1, M, F, A) ->
origin(_N, _M, _F, _A) ->
<<"in call from">>.
-format_errstr_call(ErrStr, Class, ForMForFun, As, PF, Pre0) ->
+format_errstr_call(ErrStr, Class, ForMForFun, As, PF, Pre0, Enc) ->
Pre1 = [Pre0 | n_spaces(exited_size(Class))],
- format_call(ErrStr, Pre1, ForMForFun, As, PF).
+ format_call(ErrStr, Pre1, ForMForFun, As, PF, Enc).
-format_call(ErrStr, Pre1, ForMForFun, As, PF) ->
+format_call(ErrStr, Pre1, ForMForFun, As, PF, Enc) ->
Arity = length(As),
[ErrStr |
case is_op(ForMForFun, Arity) of
{yes,Op} ->
- format_op(ErrStr, Pre1, Op, As, PF);
+ format_op(ErrStr, Pre1, Op, As, PF, Enc);
no ->
MFs = mf_to_string(ForMForFun, Arity),
I1 = iolist_size([Pre1,ErrStr|MFs]),
- S1 = pp_arguments(PF, As, I1),
- S2 = pp_arguments(PF, As, iolist_size([Pre1|MFs])),
- Long = count_nl(pp_arguments(PF, [a2345,b2345], I1)) > 0,
+ S1 = pp_arguments(PF, As, I1, Enc),
+ S2 = pp_arguments(PF, As, iolist_size([Pre1|MFs]), Enc),
+ Long = count_nl(pp_arguments(PF, [a2345,b2345], I1, Enc)) > 0,
case Long or (count_nl(S2) < count_nl(S1)) of
true ->
[$\n, Pre1, MFs, S2];
@@ -362,11 +381,11 @@ format_call(ErrStr, Pre1, ForMForFun, As, PF) ->
end
end].
-format_op(ErrStr, Pre, Op, [A1], PF) ->
+format_op(ErrStr, Pre, Op, [A1], PF, _Enc) ->
OpS = io_lib:fwrite(<<"~s ">>, [Op]),
I1 = iolist_size([ErrStr,Pre,OpS]),
[OpS | PF(A1, I1+1)];
-format_op(ErrStr, Pre, Op, [A1, A2], PF) ->
+format_op(ErrStr, Pre, Op, [A1, A2], PF, Enc) ->
I1 = iolist_size([ErrStr,Pre]),
S1 = PF(A1, I1+1),
S2 = PF(A2, I1+1),
@@ -377,33 +396,40 @@ format_op(ErrStr, Pre, Op, [A1, A2], PF) ->
[S1,Pre1,OpS,Pre1|S2];
false ->
OpS2 = io_lib:fwrite(<<" ~s ">>, [Op]),
- S2_2 = PF(A2, iolist_size([ErrStr,Pre,S1|OpS2])+1),
+ Size1 = iolist_size([ErrStr,Pre|OpS2]),
+ {Size2,S1_2} = size(Enc, S1),
+ S2_2 = PF(A2, Size1+Size2+1),
case count_nl(S2) < count_nl(S2_2) of
true ->
- [S1,Pre1,OpS,Pre1|S2];
+ [S1_2,Pre1,OpS,Pre1|S2];
false ->
- [S1,OpS2|S2_2]
+ [S1_2,OpS2|S2_2]
end
end.
-pp_arguments(PF, As, I) ->
- case {As, io_lib:printable_list(As)} of
+pp_arguments(PF, As, I, Enc) ->
+ case {As, printable_list(Enc, As)} of
{[Int | T], true} ->
L = integer_to_list(Int),
Ll = length(L),
A = list_to_atom(lists:duplicate(Ll, $a)),
- S0 = binary_to_list(iolist_to_binary(PF([A | T], I+1))),
- brackets_to_parens([$[,L,string:sub_string(S0, 2+Ll)]);
+ S0 = unicode:characters_to_list(PF([A | T], I+1), Enc),
+ brackets_to_parens([$[,L,string:sub_string(S0, 2+Ll)], Enc);
_ ->
- brackets_to_parens(PF(As, I+1))
+ brackets_to_parens(PF(As, I+1), Enc)
end.
-brackets_to_parens(S) ->
- B = iolist_to_binary(S),
+brackets_to_parens(S, Enc) ->
+ B = unicode:characters_to_binary(S, Enc),
Sz = byte_size(B) - 2,
<<$[,R:Sz/binary,$]>> = B,
[$(,R,$)].
+printable_list(latin1, As) ->
+ io_lib:printable_list(As);
+printable_list(_, As) ->
+ io_lib:printable_unicode_list(As).
+
mfa_to_string(M, F, A) ->
io_lib:fwrite(<<"~s/~w">>, [mf_to_string({M, F}, A), A]).
@@ -472,3 +498,10 @@ exited(exit) ->
<<"exception exit: ">>;
exited(throw) ->
<<"exception throw: ">>.
+
+size(latin1, S) ->
+ {iolist_size(S),S};
+size(_, S0) ->
+ S = unicode:characters_to_list(S0, unicode),
+ true = is_list(S),
+ {length(S),S}.
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index cddf345c76..400380a36d 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -78,89 +78,89 @@ obsolete_1(snmp, N, A) ->
end;
obsolete_1(snmpm, agent_info, 3) ->
- {deprecated, {snmpm, agent_info, 2}, "R16B"};
+ {removed, {snmpm, agent_info, 2}, "R16B"};
obsolete_1(snmpm, update_agent_info, 5) ->
- {deprecated, {snmpm, update_agent_info, 4}, "R16B"};
+ {removed, {snmpm, update_agent_info, 4}, "R16B"};
obsolete_1(snmpm, g, 3) ->
- {deprecated, {snmpm, sync_get, 3}, "R16B"};
+ {removed, {snmpm, sync_get, 3}, "R16B"};
obsolete_1(snmpm, g, 4) ->
- {deprecated, {snmpm, sync_get, [3,4]}, "R16B"};
+ {removed, {snmpm, sync_get, [3,4]}, "R16B"};
obsolete_1(snmpm, g, 5) ->
- {deprecated, {snmpm, sync_get, [4,5]}, "R16B"};
+ {removed, {snmpm, sync_get, [4,5]}, "R16B"};
obsolete_1(snmpm, g, 6) ->
- {deprecated, {snmpm, sync_get, [5,6]}, "R16B"};
+ {removed, {snmpm, sync_get, [5,6]}, "R16B"};
obsolete_1(snmpm, g, 7) ->
- {deprecated, {snmpm, sync_get, 6}, "R16B"};
+ {removed, {snmpm, sync_get, 6}, "R16B"};
obsolete_1(snmpm, ag, 3) ->
- {deprecated, {snmpm, async_get, 3}, "R16B"};
+ {removed, {snmpm, async_get, 3}, "R16B"};
obsolete_1(snmpm, ag, 4) ->
- {deprecated, {snmpm, async_get, [3,4]}, "R16B"};
+ {removed, {snmpm, async_get, [3,4]}, "R16B"};
obsolete_1(snmpm, ag, 5) ->
- {deprecated, {snmpm, async_get, [4,5]}, "R16B"};
+ {removed, {snmpm, async_get, [4,5]}, "R16B"};
obsolete_1(snmpm, ag, 6) ->
- {deprecated, {snmpm, async_get, [5,6]}, "R16B"};
+ {removed, {snmpm, async_get, [5,6]}, "R16B"};
obsolete_1(snmpm, ag, 7) ->
- {deprecated, {snmpm, async_get, 6}, "R16B"};
+ {removed, {snmpm, async_get, 6}, "R16B"};
obsolete_1(snmpm, gn, 3) ->
- {deprecated, {snmpm, sync_get_next, 3}, "R16B"};
+ {removed, {snmpm, sync_get_next, 3}, "R16B"};
obsolete_1(snmpm, gn, 4) ->
- {deprecated, {snmpm, sync_get_next, [3,4]}, "R16B"};
+ {removed, {snmpm, sync_get_next, [3,4]}, "R16B"};
obsolete_1(snmpm, gn, 5) ->
- {deprecated, {snmpm, sync_get_next, [4,5]}, "R16B"};
+ {removed, {snmpm, sync_get_next, [4,5]}, "R16B"};
obsolete_1(snmpm, gn, 6) ->
- {deprecated, {snmpm, sync_get_next, [5,6]}, "R16B"};
+ {removed, {snmpm, sync_get_next, [5,6]}, "R16B"};
obsolete_1(snmpm, gn, 7) ->
- {deprecated, {snmpm, sync_get_next, 6}, "R16B"};
+ {removed, {snmpm, sync_get_next, 6}, "R16B"};
obsolete_1(snmpm, agn, 3) ->
- {deprecated, {snmpm, async_get_next, 3}, "R16B"};
+ {removed, {snmpm, async_get_next, 3}, "R16B"};
obsolete_1(snmpm, agn, 4) ->
- {deprecated, {snmpm, async_get_next, [3,4]}, "R16B"};
+ {removed, {snmpm, async_get_next, [3,4]}, "R16B"};
obsolete_1(snmpm, agn, 5) ->
- {deprecated, {snmpm, async_get_next, [4,5]}, "R16B"};
+ {removed, {snmpm, async_get_next, [4,5]}, "R16B"};
obsolete_1(snmpm, agn, 6) ->
- {deprecated, {snmpm, async_get_next, [5,6]}, "R16B"};
+ {removed, {snmpm, async_get_next, [5,6]}, "R16B"};
obsolete_1(snmpm, agn, 7) ->
- {deprecated, {snmpm, async_get_next, 6}, "R16B"};
+ {removed, {snmpm, async_get_next, 6}, "R16B"};
obsolete_1(snmpm, s, 3) ->
- {deprecated, {snmpm, sync_set, 3}, "R16B"};
+ {removed, {snmpm, sync_set, 3}, "R16B"};
obsolete_1(snmpm, s, 4) ->
- {deprecated, {snmpm, sync_set, [3,4]}, "R16B"};
+ {removed, {snmpm, sync_set, [3,4]}, "R16B"};
obsolete_1(snmpm, s, 5) ->
- {deprecated, {snmpm, sync_set, [4,5]}, "R16B"};
+ {removed, {snmpm, sync_set, [4,5]}, "R16B"};
obsolete_1(snmpm, s, 6) ->
- {deprecated, {snmpm, sync_set, [5,6]}, "R16B"};
+ {removed, {snmpm, sync_set, [5,6]}, "R16B"};
obsolete_1(snmpm, s, 7) ->
- {deprecated, {snmpm, sync_set, 6}, "R16B"};
+ {removed, {snmpm, sync_set, 6}, "R16B"};
obsolete_1(snmpm, as, 3) ->
- {deprecated, {snmpm, async_set, 3}, "R16B"};
+ {removed, {snmpm, async_set, 3}, "R16B"};
obsolete_1(snmpm, as, 4) ->
- {deprecated, {snmpm, async_set, [3,4]}, "R16B"};
+ {removed, {snmpm, async_set, [3,4]}, "R16B"};
obsolete_1(snmpm, as, 5) ->
- {deprecated, {snmpm, async_set, [4,5]}, "R16B"};
+ {removed, {snmpm, async_set, [4,5]}, "R16B"};
obsolete_1(snmpm, as, 6) ->
- {deprecated, {snmpm, async_set, [5,6]}, "R16B"};
+ {removed, {snmpm, async_set, [5,6]}, "R16B"};
obsolete_1(snmpm, as, 7) ->
- {deprecated, {snmpm, async_set, 6}, "R16B"};
+ {removed, {snmpm, async_set, 6}, "R16B"};
obsolete_1(snmpm, gb, 5) ->
- {deprecated, {snmpm, sync_get_bulk, 5}, "R16B"};
+ {removed, {snmpm, sync_get_bulk, 5}, "R16B"};
obsolete_1(snmpm, gb, 6) ->
- {deprecated, {snmpm, sync_get_bulk, [5,6]}, "R16B"};
+ {removed, {snmpm, sync_get_bulk, [5,6]}, "R16B"};
obsolete_1(snmpm, gb, 7) ->
- {deprecated, {snmpm, sync_get_bulk, [6,7]}, "R16B"};
+ {removed, {snmpm, sync_get_bulk, [6,7]}, "R16B"};
obsolete_1(snmpm, gb, 8) ->
- {deprecated, {snmpm, sync_get_bulk, [7,8]}, "R16B"};
+ {removed, {snmpm, sync_get_bulk, [7,8]}, "R16B"};
obsolete_1(snmpm, gb, 9) ->
- {deprecated, {snmpm, sync_get_bulk, 8}, "R16B"};
+ {removed, {snmpm, sync_get_bulk, 8}, "R16B"};
obsolete_1(snmpm, agb, 5) ->
- {deprecated, {snmpm, async_get_bulk, 5}, "R16B"};
+ {removed, {snmpm, async_get_bulk, 5}, "R16B"};
obsolete_1(snmpm, agb, 6) ->
- {deprecated, {snmpm, async_get_bulk, [5,6]}, "R16B"};
+ {removed, {snmpm, async_get_bulk, [5,6]}, "R16B"};
obsolete_1(snmpm, agb, 7) ->
- {deprecated, {snmpm, async_get_bulk, [6,7]}, "R16B"};
+ {removed, {snmpm, async_get_bulk, [6,7]}, "R16B"};
obsolete_1(snmpm, agb, 8) ->
- {deprecated, {snmpm, async_get_bulk, [7,8]}, "R16B"};
+ {removed, {snmpm, async_get_bulk, [7,8]}, "R16B"};
obsolete_1(snmpm, agb, 9) ->
- {deprecated, {snmpm, async_get_bulk, 8}, "R16B"};
+ {removed, {snmpm, async_get_bulk, 8}, "R16B"};
%% *** MEGACO ***
@@ -347,7 +347,7 @@ obsolete_1(docb_xml_check, _, _) ->
obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver ->
{deprecated,"deprecated (will be removed in R16A); has no effect as drivers are no longer used."};
obsolete_1(ssl, pid, 1) ->
- {deprecated,"deprecated (will be removed in R17); is no longer needed"};
+ {removed,"was removed in R16; is no longer needed"};
obsolete_1(inviso, _, _) ->
{removed,"the inviso application was removed in R16"};
diff --git a/lib/stdlib/src/proplists.erl b/lib/stdlib/src/proplists.erl
index e3eda5d932..204f8e128c 100644
--- a/lib/stdlib/src/proplists.erl
+++ b/lib/stdlib/src/proplists.erl
@@ -51,20 +51,21 @@
-export_type([property/0, proplist/0]).
--type property() :: atom() | tuple().
+-type property() :: atom() | tuple().
-type proplist() :: [property()].
%% ---------------------------------------------------------------------
%% @doc Creates a normal form (minimal) representation of a property. If
-%% <code>P</code> is <code>{Key, true}</code> where <code>Key</code> is
-%% an atom, this returns <code>Key</code>, otherwise the whole term
-%% <code>P</code> is returned.
+%% <code>PropertyIn</code> is <code>{Key, true}</code> where
+%% <code>Key</code> is an atom, this returns <code>Key</code>, otherwise
+%% the whole term <code>PropertyIn</code> is returned.
%%
%% @see property/2
--spec property(Property) -> Property when
- Property :: property().
+-spec property(PropertyIn) -> PropertyOut when
+ PropertyIn :: property(),
+ PropertyOut :: property().
property({Key, true}) when is_atom(Key) ->
Key;
@@ -92,13 +93,14 @@ property(Key, Value) ->
%% ---------------------------------------------------------------------
-%% @doc Unfolds all occurences of atoms in <code>List</code> to tuples
+%% @doc Unfolds all occurences of atoms in <code>ListIn</code> to tuples
%% <code>{Atom, true}</code>.
%%
%% @see compact/1
--spec unfold(List) -> List when
- List :: [term()].
+-spec unfold(ListIn) -> ListOut when
+ ListIn :: [term()],
+ ListOut :: [term()].
unfold([P | Ps]) ->
if is_atom(P) ->
@@ -110,16 +112,17 @@ unfold([]) ->
[].
%% @doc Minimizes the representation of all entries in the list. This is
-%% equivalent to <code>[property(P) || P &lt;- List]</code>.
+%% equivalent to <code>[property(P) || P &lt;- ListIn]</code>.
%%
%% @see unfold/1
%% @see property/1
--spec compact(List) -> List when
- List :: [property()].
+-spec compact(ListIn) -> ListOut when
+ ListIn :: [property()],
+ ListOut :: [property()].
-compact(List) ->
- [property(P) || P <- List].
+compact(ListIn) ->
+ [property(P) || P <- ListIn].
%% ---------------------------------------------------------------------
@@ -199,7 +202,7 @@ is_defined(_Key, []) ->
-spec get_value(Key, List) -> term() when
Key :: term(),
- List :: List::[term()].
+ List :: [term()].
get_value(Key, List) ->
get_value(Key, List, undefined).
@@ -272,9 +275,10 @@ get_all_values(_Key, []) ->
%%
%% @see get_all_values/2
--spec append_values(Key, List) -> List when
+-spec append_values(Key, ListIn) -> ListOut when
Key :: term(),
- List :: [term()].
+ ListIn :: [term()],
+ ListOut :: [term()].
append_values(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -357,7 +361,7 @@ get_keys([], Keys) ->
-spec delete(Key, List) -> List when
Key :: term(),
- List::[term()].
+ List :: [term()].
delete(Key, [P | Ps]) ->
if is_atom(P), P =:= Key ->
@@ -374,7 +378,7 @@ delete(_, []) ->
%% ---------------------------------------------------------------------
%% @doc Substitutes keys of properties. For each entry in
-%% <code>List</code>, if it is associated with some key <code>K1</code>
+%% <code>ListIn</code>, if it is associated with some key <code>K1</code>
%% such that <code>{K1, K2}</code> occurs in <code>Aliases</code>, the
%% key of the entry is changed to <code>Key2</code>. If the same
%% <code>K1</code> occurs more than once in <code>Aliases</code>, only
@@ -388,10 +392,11 @@ delete(_, []) ->
%% @see substitute_negations/2
%% @see normalize/2
--spec substitute_aliases(Aliases, List) -> List when
+-spec substitute_aliases(Aliases, ListIn) -> ListOut when
Aliases :: [{Key, Key}],
Key :: term(),
- List::[term()].
+ ListIn :: [term()],
+ ListOut :: [term()].
substitute_aliases(As, Props) ->
[substitute_aliases_1(As, P) || P <- Props].
@@ -411,13 +416,13 @@ substitute_aliases_1([], P) ->
%% ---------------------------------------------------------------------
%% @doc Substitutes keys of boolean-valued properties and simultaneously
-%% negates their values. For each entry in <code>List</code>, if it is
+%% negates their values. For each entry in <code>ListIn</code>, if it is
%% associated with some key <code>K1</code> such that <code>{K1,
%% K2}</code> occurs in <code>Negations</code>, then if the entry was
%% <code>{K1, true}</code> it will be replaced with <code>{K2,
%% false}</code>, otherwise it will be replaced with <code>{K2,
%% true}</code>, thus changing the name of the option and simultaneously
-%% negating the value given by <code>get_bool(List)</code>. If the same
+%% negating the value given by <code>get_bool(ListIn)</code>. If the same
%% <code>K1</code> occurs more than once in <code>Negations</code>, only
%% the first occurrence is used.
%%
@@ -431,10 +436,11 @@ substitute_aliases_1([], P) ->
%% @see substitute_aliases/2
%% @see normalize/2
--spec substitute_negations(Negations, List) -> List when
+-spec substitute_negations(Negations, ListIn) -> ListOut when
Negations :: [{Key, Key}],
Key :: term(),
- List :: [term()].
+ ListIn :: [term()],
+ ListOut :: [term()].
substitute_negations(As, Props) ->
[substitute_negations_1(As, P) || P <- Props].
@@ -466,11 +472,11 @@ substitute_negations_1([], P) ->
%% @doc Expands particular properties to corresponding sets of
%% properties (or other terms). For each pair <code>{Property,
%% Expansion}</code> in <code>Expansions</code>, if <code>E</code> is
-%% the first entry in <code>List</code> with the same key as
+%% the first entry in <code>ListIn</code> with the same key as
%% <code>Property</code>, and <code>E</code> and <code>Property</code>
%% have equivalent normal forms, then <code>E</code> is replaced with
%% the terms in <code>Expansion</code>, and any following entries with
-%% the same key are deleted from <code>List</code>.
+%% the same key are deleted from <code>ListIn</code>.
%%
%% <p>For example, the following expressions all return <code>[fie, bar,
%% baz, fum]</code>:
@@ -497,9 +503,10 @@ substitute_negations_1([], P) ->
%%
%% @see normalize/2
--spec expand(Expansions, List) -> List when
+-spec expand(Expansions, ListIn) -> ListOut when
Expansions :: [{Property :: property(), Expansion :: [term()]}],
- List :: [term()].
+ ListIn :: [term()],
+ ListOut :: [term()].
expand(Es, Ps) when is_list(Ps) ->
Es1 = [{property(P), V} || {P, V} <- Es],
@@ -599,15 +606,16 @@ flatten([]) ->
%% @see expand/2
%% @see compact/1
--spec normalize(List, Stages) -> List when
- List :: [term()],
+-spec normalize(ListIn, Stages) -> ListOut when
+ ListIn :: [term()],
Stages :: [Operation],
Operation :: {'aliases', Aliases}
| {'negations', Negations}
| {'expand', Expansions},
Aliases :: [{Key, Key}],
Negations :: [{Key, Key}],
- Expansions :: [{Property :: property(), Expansion :: [term()]}].
+ Expansions :: [{Property :: property(), Expansion :: [term()]}],
+ ListOut :: [term()].
normalize(L, [{aliases, As} | Xs]) ->
normalize(substitute_aliases(As, L), Xs);
diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl
index ad25fd559c..d441f38e44 100644
--- a/lib/stdlib/src/qlc_pt.erl
+++ b/lib/stdlib/src/qlc_pt.erl
@@ -31,9 +31,6 @@
%% Also in qlc.erl.
-define(QLC_Q(L1, L2, L3, L4, LC, Os),
{call,L1,{remote,L2,{atom,L3,?APIMOD},{atom,L4,?Q}},[LC | Os]}).
--define(QLC_QQ(L1, L2, L3, L4, L5, L6, LC, Os), % packages...
- {call,L1,{remote,L2,{record_field,L3,{atom,L4,''},
- {atom,L5,?APIMOD}},{atom,L6,?Q}},[LC | Os]}).
-define(IMP_Q(L1, L2, LC, Os), {call,L,{atom,L2,?Q},[LC | Os]}).
%% Also in qlc.erl.
@@ -2475,13 +2472,6 @@ qlcmf(?QLC_Q(L1, L2, L3, L4, LC0, Os0), F, Imp, A0, No0) when length(Os0) < 2 ->
NL = make_lcid(L1, No),
{T, A} = F(NL, LC, A2),
{?QLC_Q(L1, L2, L3, L4, T, Os), A, No + 1};
-qlcmf(?QLC_QQ(L1, L2, L3, L4, L5, L6, LC0, Os0),
- F, Imp, A0, No0) when length(Os0) < 2 ->
- {Os, A1, No1} = qlcmf(Os0, F, Imp, A0, No0),
- {LC, A2, No} = qlcmf(LC0, F, Imp, A1, No1), % nested...
- NL = make_lcid(L1, No),
- {T, A} = F(NL, LC, A2),
- {?QLC_QQ(L1, L2, L3, L4, L5, L6, T, Os), A, No + 1};
qlcmf(?IMP_Q(L1, L2, LC0, Os0), F, Imp=true, A0, No0) when length(Os0) < 2 ->
{Os, A1, No1} = qlcmf(Os0, F, Imp, A0, No0),
{LC, A2, No} = qlcmf(LC0, F, Imp, A1, No1), % nested...
diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl
index 3fd6c81e5f..e6f05b71d4 100644
--- a/lib/stdlib/src/sets.erl
+++ b/lib/stdlib/src/sets.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -17,7 +18,7 @@
%% %CopyrightEnd%
%%
-%% We use the dynamic hashing techniques by Per-�ke Larsson as
+%% We use the dynamic hashing techniques by Per-Åke Larsson as
%% described in "The Design and Implementation of Dynamic Hashing for
%% Sets and Tables in Icon" by Griswold and Townsend. Much of the
%% terminology comes from that paper as well.
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index dc450f0ee6..5c929d2f51 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -128,7 +128,7 @@ start_restricted(RShMod) when is_atom(RShMod) ->
error_logger:error_report(
lists:flatten(
io_lib:fwrite(
- <<"Restricted shell module ~w not found: ~p\n">>,
+ "Restricted shell module ~w not found: ~"++cs_p() ++"\n",
[RShMod,What]))),
Error
end.
@@ -139,16 +139,6 @@ stop_restricted() ->
application:unset_env(stdlib, restricted_shell),
exit(restricted_shell_stopped).
-default_packages() ->
- [].
-%%% ['erl','erl.lang'].
-
-default_modules() ->
- [].
-%%% [{pdict, 'erl.lang.proc.pdict'},
-%%% {keylist, 'erl.lang.list.keylist'},
-%%% {debug, 'erl.system.debug'}].
-
-spec server(boolean(), boolean()) -> 'terminated'.
server(NoCtrlG, StartSync) ->
@@ -183,16 +173,7 @@ server(StartSync) ->
end
end,
%% Our spawner has fixed the process groups.
- Bs0 = erl_eval:new_bindings(),
- Bs = lists:foldl(fun ({K, V}, D) ->
- erl_eval:add_binding({module,K}, V, D)
- end,
- lists:foldl(fun (P, D) ->
- import_all(P, D)
- end,
- Bs0, default_packages()),
- default_modules()),
- %% io:fwrite("Imported modules: ~p.\n", [erl_eval:bindings(Bs)]),
+ Bs = erl_eval:new_bindings(),
%% Use an Ets table for record definitions. It takes too long to
%% send a huge term to and from the evaluator. Ets makes it
@@ -230,9 +211,10 @@ server(StartSync) ->
ok;
{RShMod2,What2} ->
io:fwrite(
- <<"Warning! Restricted shell module ~w not found: ~p.\n"
- "Only the commands q() and init:stop() will be allowed!\n">>,
- [RShMod2,What2]),
+ ("Warning! Restricted shell module ~w not found: ~"
+ ++cs_p()++".\n"
+ "Only the commands q() and init:stop() will be allowed!\n"),
+ [RShMod2,What2]),
application:set_env(stdlib, restricted_shell, ?MODULE)
end,
@@ -244,7 +226,7 @@ server_loop(N0, Eval_0, Bs00, RT, Ds00, History0, Results0) ->
{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,_EndLine} ->
+ {ok,Es0} ->
case expand_hist(Es0, N) of
{ok,Es} ->
{V,Eval,Bs,Ds} = shell_cmd(Es, Eval0, Bs0, RT, Ds0, cmd),
@@ -263,11 +245,11 @@ server_loop(N0, Eval_0, Bs00, RT, Ds00, History0, Results0) ->
end,
server_loop(N, Eval, Bs, RT, Ds, History, Results);
{error,E} ->
- fwrite_severity(benign, <<"~s">>, [E]),
+ fwrite_severity(benign, <<"~ts">>, [E]),
server_loop(N0, Eval0, Bs0, RT, Ds0, History0, Results0)
end;
- {error,{Line,Mod,What},_EndLine} ->
- fwrite_severity(benign, <<"~w: ~s">>,
+ {error,{Line,Mod,What}} ->
+ fwrite_severity(benign, <<"~w: ~ts">>,
[Line, Mod:format_error(What)]),
server_loop(N0, Eval0, Bs0, RT, Ds0, History0, Results0);
{error,terminated} -> %Io process terminated
@@ -277,20 +259,35 @@ server_loop(N0, Eval_0, Bs00, RT, Ds00, History0, Results0) ->
exit(Eval0, kill),
{_,Eval,_,_} = shell_rep(Eval0, Bs0, RT, Ds0),
server_loop(N0, Eval, Bs0, RT, Ds0, History0, Results0);
- {error,tokens} -> %Most probably unicode > 255
+ {error,tokens} -> %Most probably character > 255
fwrite_severity(benign, <<"~w: Invalid tokens.">>,
[N]),
server_loop(N0, Eval0, Bs0, RT, Ds0, History0, Results0);
- {eof,_EndLine} ->
- fwrite_severity(fatal, <<"Terminating erlang (~w)">>, [node()]),
- halt();
eof ->
fwrite_severity(fatal, <<"Terminating erlang (~w)">>, [node()]),
halt()
end.
get_command(Prompt, Eval, Bs, RT, Ds) ->
- Parse = fun() -> exit(io:parse_erl_exprs(Prompt)) end,
+ Parse =
+ fun() ->
+ exit(
+ case
+ io:scan_erl_exprs(group_leader(), Prompt, 1, [unicode])
+ of
+ {ok,Toks,_EndPos} ->
+ erl_parse:parse_exprs(Toks);
+ {eof,_EndPos} ->
+ eof;
+ {error,ErrorInfo,_EndPos} ->
+ %% Skip the rest of the line:
+ _ = io:get_line(''),
+ {error,ErrorInfo};
+ Else ->
+ Else
+ end
+ )
+ end,
Pid = spawn_link(Parse),
get_command1(Pid, Eval, Bs, RT, Ds).
@@ -337,7 +334,7 @@ get_prompt_func() ->
end.
bad_prompt_func(M) ->
- fwrite_severity(benign, <<"Bad prompt function: ~p">>, [M]).
+ fwrite_severity(benign, "Bad prompt function: ~"++cs_p(), [M]).
default_prompt(N) ->
%% Don't bother flattening the list irrespective of what the
@@ -453,7 +450,8 @@ expand_bin_elements([{bin_element,L,E,Sz,Ts}|Fs], C) ->
no_command(N) ->
throw({error,
- io_lib:fwrite(<<"~s: command not found">>, [erl_pp:expr(N)])}).
+ io_lib:fwrite(<<"~ts: command not found">>,
+ [erl_pp:expr(N, enc())])}).
%% add_cmd(Number, Expressions, Value)
%% get_cmd(Number, CurrentCommand)
@@ -518,7 +516,7 @@ shell_rep(Ev, Bs0, RT, Ds0) ->
{shell_rep,Ev,{value,V,Bs,Ds}} ->
{V,Ev,Bs,Ds};
{shell_rep,Ev,{command_error,{Line,M,Error}}} ->
- fwrite_severity(benign, <<"~w: ~s">>,
+ fwrite_severity(benign, <<"~w: ~ts">>,
[Line, M:format_error(Error)]),
{{'EXIT',Error},Ev,Bs0,Ds0};
{shell_req,Ev,get_cmd} ->
@@ -570,9 +568,10 @@ report_exception(Class, Severity, {Reason,Stacktrace}, RT) ->
I = iolist_size(Tag) + 1,
PF = fun(Term, I1) -> pp(Term, I1, RT) end,
SF = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
- io:requests([{put_chars, Tag},
- {put_chars,
- lib:format_exception(I, Class, Reason, Stacktrace, SF, PF)},
+ Enc = encoding(),
+ Str = lib:format_exception(I, Class, Reason, Stacktrace, SF, PF, Enc),
+ io:requests([{put_chars, latin1, Tag},
+ {put_chars, unicode, Str},
nl]).
start_eval(Bs, RT, Ds) ->
@@ -671,7 +670,8 @@ exprs([E0|Es], Bs1, RT, Lf, Ef, Bs0, W) ->
if
Es =:= [] ->
VS = pp(V0, 1, RT),
- [io:requests([{put_chars, VS}, nl]) || W =:= cmd],
+ [io:requests([{put_chars, unicode, VS}, nl]) ||
+ W =:= cmd],
%% Don't send the result back if it will be
%% discarded anyway.
V = if
@@ -753,7 +753,7 @@ used_records(E) ->
{expr, E}.
fwrite_severity(Severity, S, As) ->
- io:fwrite(<<"~s\n">>, [format_severity(Severity, S, As)]).
+ io:fwrite(<<"~ts\n">>, [format_severity(Severity, S, As)]).
format_severity(Severity, S, As) ->
add_severity(Severity, io_lib:fwrite(S, As)).
@@ -958,13 +958,13 @@ local_func(rd, [{atom,_,RecName},RecDef0], Bs, _Shell, RT, _Lf, _Ef) ->
RecDef = expand_value(RecDef0),
RDs = lists:flatten(erl_pp:expr(RecDef)),
Attr = lists:concat(["-record('", RecName, "',", RDs, ")."]),
- {ok, Tokens, _} = erl_scan:string(Attr),
+ {ok, Tokens, _} = erl_scan:string(Attr, 1, [unicode]),
case erl_parse:parse_form(Tokens) of
{ok,AttrForm} ->
[RN] = add_records([AttrForm], Bs, RT),
{value,RN,Bs};
{error,{_Line,M,ErrDesc}} ->
- ErrStr = io_lib:fwrite(<<"~s">>, [M:format_error(ErrDesc)]),
+ ErrStr = io_lib:fwrite(<<"~ts">>, [M:format_error(ErrDesc)]),
exit(lists:flatten(ErrStr))
end;
local_func(rd, [_,_], _Bs, _Shell, _RT, _Lf, _Ef) ->
@@ -988,11 +988,13 @@ local_func(rl, [A], Bs0, _Shell, RT, Lf, Ef) ->
{value,list_records(record_defs(RT, listify(Recs))),Bs};
local_func(rp, [A], Bs0, _Shell, RT, Lf, Ef) ->
{[V],Bs} = expr_list([A], Bs0, Lf, Ef),
- W = columns(),
- io:requests([{put_chars,
- io_lib_pretty:print(V, 1, W, -1, ?CHAR_MAX,
- record_print_fun(RT))},
- nl]),
+ Cs = io_lib_pretty:print(V, ([{column, 1},
+ {line_length, columns()},
+ {depth, -1},
+ {max_chars, ?CHAR_MAX},
+ {record_print_fun, record_print_fun(RT)}]
+ ++ enc())),
+ io:requests([{put_chars, unicode, Cs}, nl]),
{value,ok,Bs};
local_func(rr, [A], Bs0, _Shell, RT, Lf, Ef) ->
{[File],Bs} = expr_list([A], Bs0, Lf, Ef),
@@ -1012,38 +1014,6 @@ local_func(which, [{atom,_,M}], Bs, _Shell, _RT, _Lf, _Ef) ->
end;
local_func(which, [_Other], _Bs, _Shell, _RT, _Lf, _Ef) ->
erlang:raise(error, function_clause, [{shell,which,1}]);
-local_func(import, [M], Bs, _Shell, _RT, _Lf, _Ef) ->
- case erl_parse:package_segments(M) of
- error -> erlang:raise(error, function_clause, [{shell,import,1}]);
- M1 ->
- Mod = packages:concat(M1),
- case packages:is_valid(Mod) of
- true ->
- Key = list_to_atom(packages:last(Mod)),
- Mod1 = list_to_atom(Mod),
- {value,ok,erl_eval:add_binding({module,Key}, Mod1, Bs)};
- false ->
- exit({{bad_module_name, Mod}, [{shell,import,1}]})
- end
- end;
-local_func(import_all, [P], Bs0, _Shell, _RT, _Lf, _Ef) ->
- case erl_parse:package_segments(P) of
- error -> erlang:raise(error, function_clause, [{shell,import_all,1}]);
- P1 ->
- Name = packages:concat(P1),
- case packages:is_valid(Name) of
- true ->
- Bs1 = import_all(Name, Bs0),
- {value,ok,Bs1};
- false ->
- exit({{bad_package_name, Name},
- [{shell,import_all,1}]})
- end
- end;
-local_func(use, [M], Bs, Shell, RT, Lf, Ef) ->
- local_func(import, [M], Bs, Shell, RT, Lf, Ef);
-local_func(use_all, [M], Bs, Shell, RT, Lf, Ef) ->
- local_func(import_all, [M], Bs, Shell, RT, Lf, Ef);
local_func(history, [{integer,_,N}], Bs, _Shell, _RT, _Lf, _Ef) ->
{value,history(N),Bs};
local_func(history, [_Other], _Bs, _Shell, _RT, _Lf, _Ef) ->
@@ -1166,7 +1136,7 @@ add_records(RAs, Bs0, RT) ->
case check_command([], Bs1) of
{error,{_Line,M,ErrDesc}} ->
%% A source file that has not been compiled.
- ErrStr = io_lib:fwrite(<<"~s">>, [M:format_error(ErrDesc)]),
+ ErrStr = io_lib:fwrite(<<"~ts">>, [M:format_error(ErrDesc)]),
exit(lists:flatten(ErrStr));
ok ->
true = ets:insert(RT, Recs),
@@ -1323,15 +1293,6 @@ record_attrs(Forms) ->
%%% End of reading record information from file(s)
-import_all(P, Bs0) ->
- Ms = packages:find_modules(P),
- lists:foldl(fun (M, Bs) ->
- Key = list_to_atom(M),
- M1 = list_to_atom(packages:concat(P, M)),
- erl_eval:add_binding({module,Key}, M1, Bs)
- end,
- Bs0, Ms).
-
shell_req(Shell, Req) ->
Shell ! {shell_req,self(),Req},
receive
@@ -1343,25 +1304,25 @@ list_commands([{{N,command},Es0}, {{N,result}, V} |Ds], RT) ->
VS = pp(V, 4, RT),
Ns = io_lib:fwrite(<<"~w: ">>, [N]),
I = iolist_size(Ns),
- io:requests([{put_chars, Ns},
- {format,<<"~s\n">>,[erl_pp:exprs(Es, I, none)]},
+ io:requests([{put_chars, latin1, Ns},
+ {format,<<"~ts\n">>,[erl_pp:exprs(Es, I, enc())]},
{format,<<"-> ">>,[]},
- {put_chars, VS},
+ {put_chars, unicode, VS},
nl]),
list_commands(Ds, RT);
list_commands([{{N,command},Es0} |Ds], RT) ->
Es = prep_list_commands(Es0),
Ns = io_lib:fwrite(<<"~w: ">>, [N]),
I = iolist_size(Ns),
- io:requests([{put_chars, Ns},
- {format,<<"~s\n">>,[erl_pp:exprs(Es, I, none)]}]),
+ io:requests([{put_chars, latin1, Ns},
+ {format,<<"~ts\n">>,[erl_pp:exprs(Es, I, enc())]}]),
list_commands(Ds, RT);
list_commands([_D|Ds], RT) ->
list_commands(Ds, RT);
list_commands([], _RT) -> ok.
list_bindings([{{module,M},Val}|Bs], RT) ->
- io:fwrite(<<"~p is ~p\n">>, [M,Val]),
+ io:fwrite(<<"~w is ~w\n">>, [M,Val]),
list_bindings(Bs, RT);
list_bindings([{Name,Val}|Bs], RT) ->
case erl_eval:fun_data(Val) of
@@ -1369,13 +1330,13 @@ list_bindings([{Name,Val}|Bs], RT) ->
FCs = expand_value(FCs0), % looks nicer
F = {'fun',0,{clauses,FCs}},
M = {match,0,{var,0,Name},F},
- io:fwrite(<<"~s\n">>, [erl_pp:expr(M)]);
+ io:fwrite(<<"~ts\n">>, [erl_pp:expr(M, enc())]);
false ->
Namel = io_lib:fwrite(<<"~s = ">>, [Name]),
Nl = iolist_size(Namel)+1,
ValS = pp(Val, Nl, RT),
- io:requests([{put_chars, Namel},
- {put_chars, ValS},
+ io:requests([{put_chars, latin1, Namel},
+ {put_chars, unicode, ValS},
nl])
end,
list_bindings(Bs, RT);
@@ -1384,7 +1345,7 @@ list_bindings([], _RT) ->
list_records(Records) ->
lists:foreach(fun({_Name,Attr}) ->
- io:fwrite(<<"~s">>, [erl_pp:attribute(Attr)])
+ io:fwrite(<<"~ts">>, [erl_pp:attribute(Attr, enc())])
end, Records).
record_defs(RT, Names) ->
@@ -1427,8 +1388,20 @@ get_history_and_results() ->
{History, erlang:min(Results, History)}.
pp(V, I, RT) ->
- io_lib_pretty:print(V, I, columns(), ?LINEMAX, ?CHAR_MAX,
- record_print_fun(RT)).
+ pp(V, I, RT, enc()).
+
+pp(V, I, RT, Enc) ->
+ io_lib_pretty:print(V, ([{column, I}, {line_length, columns()},
+ {depth, ?LINEMAX}, {max_chars, ?CHAR_MAX},
+ {record_print_fun, record_print_fun(RT)}]
+ ++ Enc)).
+
+%% Control sequence 'p' possibly with Unicode translation modifier
+cs_p() ->
+ case encoding() of
+ latin1 -> "p";
+ unicode -> "tp"
+ end.
columns() ->
case io:columns() of
@@ -1436,9 +1409,20 @@ columns() ->
_ -> 80
end.
+encoding() ->
+ [{encoding, Encoding}] = enc(),
+ Encoding.
+
+enc() ->
+ case lists:keyfind(encoding, 1, io:getopts()) of
+ false -> [{encoding,latin1}]; % should never happen
+ Enc -> [Enc]
+ end.
+
garb(Shell) ->
erlang:garbage_collect(Shell),
catch erlang:garbage_collect(whereis(user)),
+ catch erlang:garbage_collect(whereis(group)),
catch erlang:garbage_collect(group_leader()),
erlang:garbage_collect().
@@ -1458,7 +1442,8 @@ check_env(V) ->
ok;
{ok, Val} ->
Txt = io_lib:fwrite(
- <<"Invalid value of STDLIB configuration parameter ~p: ~p\n">>,
+ ("Invalid value of STDLIB configuration parameter ~w: ~"
+ ++cs_p()++"\n"),
[V, Val]),
error_logger:info_report(lists:flatten(Txt))
end.
diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl
index fc029a582f..03f0a19f14 100644
--- a/lib/stdlib/src/string.erl
+++ b/lib/stdlib/src/string.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -257,7 +258,7 @@ chars(C, N, Tail) when N > 0 ->
chars(C, 0, Tail) when is_integer(C) ->
Tail.
-%% Torbj�rn's bit.
+%% Torbjörn's bit.
%%% COPIES %%%
diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl
index 4dd70ad425..2d6287814e 100644
--- a/lib/stdlib/src/sys.erl
+++ b/lib/stdlib/src/sys.erl
@@ -39,7 +39,18 @@
| {'in', Msg :: _, From :: _}
| {'out', Msg :: _, To :: _}
| term().
--opaque dbg_opt() :: list().
+-opaque dbg_opt() :: {'trace', 'true'}
+ | {'log',
+ {N :: non_neg_integer(),
+ [{Event :: system_event(),
+ FuncState :: _,
+ FormFunc :: dbg_fun()}]}}
+ | {'statistics', {file:date_time(),
+ {'reductions', non_neg_integer()},
+ MessagesIn :: non_neg_integer(),
+ MessagesOut :: non_neg_integer()}}
+ | {'log_to_file', file:io_device()}
+ | {Func :: dbg_fun(), FuncState :: term()}.
-type dbg_fun() :: fun((FuncState :: _,
Event :: system_event(),
ProcState :: _) -> 'done' | (NewFuncState :: _)).
@@ -47,24 +58,22 @@
%%-----------------------------------------------------------------
%% System messages
%%-----------------------------------------------------------------
--spec suspend(Name) -> Void when
- Name :: name(),
- Void :: term().
+-spec suspend(Name) -> 'ok' when
+ Name :: name().
suspend(Name) -> send_system_msg(Name, suspend).
--spec suspend(Name, Timeout) -> Void when
+
+-spec suspend(Name, Timeout) -> 'ok' when
Name :: name(),
- Timeout :: timeout(),
- Void :: term().
+ Timeout :: timeout().
suspend(Name, Timeout) -> send_system_msg(Name, suspend, Timeout).
--spec resume(Name) -> Void when
- Name :: name(),
- Void :: term().
+-spec resume(Name) -> 'ok' when
+ Name :: name().
resume(Name) -> send_system_msg(Name, resume).
--spec resume(Name, Timeout) -> Void when
+
+-spec resume(Name, Timeout) -> 'ok' when
Name :: name(),
- Timeout :: timeout(),
- Void :: term().
+ Timeout :: timeout().
resume(Name, Timeout) -> send_system_msg(Name, resume, Timeout).
-spec get_status(Name) -> Status when
@@ -73,9 +82,10 @@ resume(Name, Timeout) -> send_system_msg(Name, resume, Timeout).
SItem :: (PDict :: [{Key :: term(), Value :: term()}])
| (SysState :: 'running' | 'suspended')
| (Parent :: pid())
- | (Dbg :: dbg_opt())
+ | (Dbg :: [dbg_opt()])
| (Misc :: term()).
get_status(Name) -> send_system_msg(Name, get_status).
+
-spec get_status(Name, Timeout) -> Status when
Name :: name(),
Timeout :: timeout(),
@@ -83,7 +93,7 @@ get_status(Name) -> send_system_msg(Name, get_status).
SItem :: (PDict :: [{Key :: term(), Value :: term()}])
| (SysState :: 'running' | 'suspended')
| (Parent :: pid())
- | (Dbg :: dbg_opt())
+ | (Dbg :: [dbg_opt()])
| (Misc :: term()).
get_status(Name, Timeout) -> send_system_msg(Name, get_status, Timeout).
@@ -95,6 +105,7 @@ get_status(Name, Timeout) -> send_system_msg(Name, get_status, Timeout).
Reason :: term().
change_code(Name, Mod, Vsn, Extra) ->
send_system_msg(Name, {change_code, Mod, Vsn, Extra}).
+
-spec change_code(Name, Module, OldVsn, Extra, Timeout) ->
'ok' | {error, Reason} when
Name :: name(),
@@ -191,35 +202,33 @@ no_debug(Name) -> send_system_msg(Name, {debug, no_debug}).
Timeout :: timeout().
no_debug(Name, Timeout) -> send_system_msg(Name, {debug, no_debug}, Timeout).
--spec install(Name, FuncSpec) -> Void when
+-spec install(Name, FuncSpec) -> 'ok' when
Name :: name(),
FuncSpec :: {Func, FuncState},
Func :: dbg_fun(),
- FuncState :: term(),
- Void :: term().
+ FuncState :: term().
install(Name, {Func, FuncState}) ->
send_system_msg(Name, {debug, {install, {Func, FuncState}}}).
--spec install(Name, FuncSpec, Timeout) -> Void when
+
+-spec install(Name, FuncSpec, Timeout) -> 'ok' when
Name :: name(),
FuncSpec :: {Func, FuncState},
Func :: dbg_fun(),
FuncState :: term(),
- Timeout :: timeout(),
- Void :: term().
+ Timeout :: timeout().
install(Name, {Func, FuncState}, Timeout) ->
send_system_msg(Name, {debug, {install, {Func, FuncState}}}, Timeout).
--spec remove(Name, Func) -> Void when
+-spec remove(Name, Func) -> 'ok' when
Name :: name(),
- Func :: dbg_fun(),
- Void :: term().
+ Func :: dbg_fun().
remove(Name, Func) ->
send_system_msg(Name, {debug, {remove, Func}}).
--spec remove(Name, Func, Timeout) -> Void when
+
+-spec remove(Name, Func, Timeout) -> 'ok' when
Name :: name(),
Func :: dbg_fun(),
- Timeout :: timeout(),
- Void :: term().
+ Timeout :: timeout().
remove(Name, Func, Timeout) ->
send_system_msg(Name, {debug, {remove, Func}}, Timeout).
@@ -245,18 +254,13 @@ mfa(Name, {change_code, Mod, Vsn, Extra}) ->
{sys, change_code, [Name, Mod, Vsn, Extra]};
mfa(Name, Atom) ->
{sys, Atom, [Name]}.
+
mfa(Name, Req, Timeout) ->
{M, F, A} = mfa(Name, Req),
{M, F, A ++ [Timeout]}.
%%-----------------------------------------------------------------
%% Func: handle_system_msg/6
-%% Args: Msg ::= term()
-%% From ::= {pid(),Ref} but don't count on that
-%% Parent ::= pid()
-%% Module ::= atom()
-%% Debug ::= [debug_opts()]
-%% Misc ::= term()
%% Purpose: Used by a process module that wishes to take care of
%% system messages. The process receives a {system, From,
%% Msg} message, and passes the Msg to this function.
@@ -268,14 +272,14 @@ mfa(Name, Req, Timeout) ->
%% The Module must export system_continue/3, system_terminate/4
%% and format_status/2 for status information.
%%-----------------------------------------------------------------
--spec handle_system_msg(Msg, From, Parent, Module, Debug, Misc) -> Void when
+-spec handle_system_msg(Msg, From, Parent, Module, Debug, Misc) ->
+ no_return() when
Msg :: term(),
From :: {pid(), Tag :: _},
Parent :: pid(),
Module :: module(),
Debug :: [dbg_opt()],
- Misc :: term(),
- Void :: term().
+ Misc :: term().
handle_system_msg(Msg, From, Parent, Module, Debug, Misc) ->
handle_system_msg(running, Msg, From, Parent, Module, Debug, Misc, false).
@@ -294,10 +298,6 @@ handle_system_msg(SysState, Msg, From, Parent, Mod, Debug, Misc, Hib) ->
%%-----------------------------------------------------------------
%% Func: handle_debug/4
-%% Args: Debug ::= [debug_opts()]
-%% Func ::= {M,F} | fun() arity 3
-%% State ::= term()
-%% Event ::= {in, Msg} | {in, Msg, From} | {out, Msg, To} | term()
%% Purpose: Called by a process that wishes to debug an event.
%% Func is a formatting function, called as Func(Device, Event).
%% Returns: [debug_opts()]
@@ -453,6 +453,7 @@ print_event(Dev, {Event, State, FormFunc}) ->
FormFunc(Dev, Event, State).
init_stat() -> {erlang:localtime(), process_info(self(), reductions), 0, 0}.
+
get_stat({Time, {reductions, Reds}, In, Out}) ->
{reductions, Reds2} = process_info(self(), reductions),
[{start_time, Time}, {current_time, erlang:localtime()},
@@ -492,9 +493,8 @@ get_debug2(Item, Debug, Default) ->
_ -> Default
end.
--spec print_log(Debug) -> Void when
- Debug :: [dbg_opt()],
- Void :: term().
+-spec print_log(Debug) -> 'ok' when
+ Debug :: [dbg_opt()].
print_log(Debug) ->
{_N, Logs} = get_debug(log, Debug, {0, []}),
lists:foreach(fun print_event/1,
@@ -511,8 +511,6 @@ close_log_file(Debug) ->
%%-----------------------------------------------------------------
%% Func: debug_options/1
-%% Args: [trace|log|{log,N}|statistics|{log_to_file, FileName}|
-%% {install, {Func, FuncState}}]
%% Purpose: Initiate a debug structure. Called by a process that
%% wishes to initiate the debug structure without the
%% system messages.
@@ -521,7 +519,11 @@ close_log_file(Debug) ->
-spec debug_options(Options) -> [dbg_opt()] when
Options :: [Opt],
- Opt :: 'trace' | 'log' | 'statistics' | {'log_to_file', FileName}
+ Opt :: 'trace'
+ | 'log'
+ | {'log', pos_integer()}
+ | 'statistics'
+ | {'log_to_file', FileName}
| {'install', FuncSpec},
FileName :: file:name(),
FuncSpec :: {Func, FuncState},
@@ -529,6 +531,7 @@ close_log_file(Debug) ->
FuncState :: term().
debug_options(Options) ->
debug_options(Options, []).
+
debug_options([trace | T], Debug) ->
debug_options(T, install_debug(trace, true, Debug));
debug_options([log | T], Debug) ->
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl
index 7b8650f224..b28df94221 100644
--- a/lib/stdlib/test/base64_SUITE.erl
+++ b/lib/stdlib/test/base64_SUITE.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -179,7 +180,7 @@ mime_decode(Config) when is_list(Config) ->
<<"o">> = base64:mime_decode(<<"b=w=====">>),
%% Test misc white space and illegals with embedded padding
<<"one">> = base64:mime_decode(<<" b~2=\r\n5()l===">>),
- <<"on">> = base64:mime_decode(<<"\tb =2\"�4=�= ==">>),
+ <<"on">> = base64:mime_decode(<<"\tb =2\"¤4=¤= ==">>),
<<"o">> = base64:mime_decode(<<"\nb=w=====">>),
%% Two pads
<<"Aladdin:open sesame">> =
@@ -188,7 +189,7 @@ mime_decode(Config) when is_list(Config) ->
<<"Hello World!!">> = base64:mime_decode(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
%% No pad
<<"Aladdin:open sesam">> =
- base64:mime_decode("QWxhZGRpbjpvcG�\")(VuIHNlc2Ft"),
+ base64:mime_decode("QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft"),
%% Encoded base 64 strings may be divided by non base 64 chars.
%% In this cases whitespaces.
<<"0123456789!@#0^&*();:<>,. []{}">> =
@@ -222,7 +223,7 @@ mime_decode_to_string(Config) when is_list(Config) ->
"o" = base64:mime_decode_to_string(<<"b=w=====">>),
%% Test misc white space and illegals with embedded padding
"one" = base64:mime_decode_to_string(<<" b~2=\r\n5()l===">>),
- "on" = base64:mime_decode_to_string(<<"\tb =2\"�4=�= ==">>),
+ "on" = base64:mime_decode_to_string(<<"\tb =2\"¤4=¤= ==">>),
"o" = base64:mime_decode_to_string(<<"\nb=w=====">>),
%% Two pads
"Aladdin:open sesame" =
@@ -231,7 +232,7 @@ mime_decode_to_string(Config) when is_list(Config) ->
"Hello World!!" = base64:mime_decode_to_string(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
%% No pad
"Aladdin:open sesam" =
- base64:mime_decode_to_string("QWxhZGRpbjpvcG�\")(VuIHNlc2Ft"),
+ base64:mime_decode_to_string("QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft"),
%% Encoded base 64 strings may be divided by non base 64 chars.
%% In this cases whitespaces.
"0123456789!@#0^&*();:<>,. []{}" =
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index bac59a3107..9b6f628aa9 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1331,9 +1332,9 @@ one_random_number(N) ->
one_random(N) ->
M = ((N - 1) rem 68) + 1,
element(M,{$a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,
- $u,$v,$w,$x,$y,$z,$�,$�,$�,$A,$B,$C,$D,$E,$F,$G,$H,
- $I,$J,$K,$L,$M,$N,$O,$P,$Q,$R,$S,$T,$U,$V,$W,$X,$Y,$Z,$�,
- $�,$�,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9}).
+ $u,$v,$w,$x,$y,$z,$å,$ä,$ö,$A,$B,$C,$D,$E,$F,$G,$H,
+ $I,$J,$K,$L,$M,$N,$O,$P,$Q,$R,$S,$T,$U,$V,$W,$X,$Y,$Z,$Å,
+ $Ä,$Ö,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9}).
random_number({Min,Max}) -> % Min and Max are *length* of number in
% decimal positions
diff --git a/lib/stdlib/test/digraph_SUITE.erl b/lib/stdlib/test/digraph_SUITE.erl
index 1d1326d60e..ed01b32a59 100644
--- a/lib/stdlib/test/digraph_SUITE.erl
+++ b/lib/stdlib/test/digraph_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -400,7 +400,7 @@ sane1(G) ->
lists:foreach(
fun(V) ->
InEs = digraph:in_edges(G, V),
- %% Nu har man *alla* inkanter f�r V
+ %% *All* in-edoges of V
lists:foreach(
fun(E) ->
case digraph:edge(G, E) of
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 77c615d6d9..606bbbcbb2 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -25,7 +25,7 @@
variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1,
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1,
- otp_8562/1, otp_8665/1, otp_8911/1]).
+ otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1]).
-export([epp_parse_erl_form/2]).
@@ -67,7 +67,7 @@ all() ->
{group, variable}, otp_4870, otp_4871, otp_5362, pmod,
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
overload_mac, otp_8388, otp_8470, otp_8503, otp_8562,
- otp_8665, otp_8911].
+ otp_8665, otp_8911, otp_10302].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -582,12 +582,13 @@ otp_8130(suite) ->
otp_8130(Config) when is_list(Config) ->
true = os:putenv("epp_inc1", "stdlib"),
Ts = [{otp_8130_1,
- %% The scanner handles UNICODE in a special way. Hopefully
- %% temporarily.
<<"-define(M(A), ??A). "
"t() -> "
- " \"{ 34 , [ $1 , 2730 ] , \\\"34\\\" , X . a , 2730 }\" = "
- " ?M({34,\"1\\x{aaa}\",\"34\",X.a,$\\x{aaa}}), ok. ">>,
+ " L = \"{ 34 , \\\"1\\\\x{AAA}\\\" , \\\"34\\\" , X . a , $\\\\x{AAA} }\", "
+ " R = ?M({34,\"1\\x{aaa}\",\"34\",X.a,$\\x{aaa}}),"
+ " Lt = erl_scan:string(L, 1, [unicode]),"
+ " Rt = erl_scan:string(R, 1, [unicode]),"
+ " Lt = Rt, ok. ">>,
ok},
{otp_8130_2,
@@ -1284,6 +1285,75 @@ otp_8665(Config) when is_list(Config) ->
?line [] = compile(Config, Cs),
ok.
+otp_10302(doc) ->
+ "OTP-10302. Unicode characters scanner/parser.";
+otp_10302(suite) ->
+ [];
+otp_10302(Config) when is_list(Config) ->
+ %% Two messages (one too many). Keeps otp_4871 happy.
+ Cs = [{otp_8562,
+ <<"%% coding: utf-8\n \n \x{E4}">>,
+ {errors,[{3,epp,cannot_parse},
+ {3,file_io_server,invalid_unicode}],[]}}
+ ],
+ [] = compile(Config, Cs),
+ Dir = ?config(priv_dir, Config),
+ File = filename:join(Dir, "otp_10302.erl"),
+ utf8 = encoding("coding: utf-8", File),
+ utf8 = encoding("coding: UTF-8", File),
+ latin1 = encoding("coding: Latin-1", File),
+ latin1 = encoding("coding: latin-1", File),
+ none = encoding_com("coding: utf-8", File),
+ none = encoding_com("\n\n%% coding: utf-8", File),
+ none = encoding_nocom("\n\n coding: utf-8", File),
+ utf8 = encoding_com("\n%% coding: utf-8", File),
+ utf8 = encoding_nocom("\n coding: utf-8", File),
+ none = encoding("coding: \nutf-8", File),
+ latin1 = encoding("Encoding : latin-1", File),
+ utf8 = encoding("ccoding: UTF-8", File),
+ utf8 = encoding("coding= utf-8", File),
+ utf8 = encoding_com(" %% coding= utf-8", File),
+ utf8 = encoding("coding = utf-8", File),
+ none = encoding("coding: utf-16 coding: utf-8", File), %first is bad
+ none = encoding("Coding: utf-8", File), %capital c
+ utf8 = encoding("-*- coding: utf-8 -*-", File),
+ utf8 = encoding("-*-coding= utf-8-*-", File),
+ utf8 = encoding("codingcoding= utf-8", File),
+ ok = prefix("coding: utf-8", File, utf8),
+
+ "coding: latin-1" = epp:encoding_to_string(latin1),
+ "coding: utf-8" = epp:encoding_to_string(utf8),
+ true = lists:member(epp:default_encoding(), [latin1, utf8]),
+
+ ok.
+
+prefix(S, File, Enc) ->
+ prefix(0, S, File, Enc).
+
+prefix(100, _S, _File, _) ->
+ ok;
+prefix(N, S, File, Enc) ->
+ Enc = encoding(lists:duplicate(N, $\s) ++ S, File),
+ prefix(N+1, S, File, Enc).
+
+encoding(Enc, File) ->
+ E = encoding_com("%% " ++ Enc, File),
+ none = encoding_com(Enc, File),
+ E = encoding_nocom(Enc, File).
+
+encoding_com(Enc, File) ->
+ ok = file:write_file(File, Enc),
+ {ok, Fd} = file:open(File, [read]),
+ E = epp:set_encoding(Fd),
+ ok = file:close(Fd),
+ E = epp:read_encoding(File).
+
+encoding_nocom(Enc, File) ->
+ ok = file:write_file(File, Enc),
+ {ok, Fd} = file:open(File, [read]),
+ ok = file:close(Fd),
+ epp:read_encoding(File, [{in_comment_only, false}]).
+
check(Config, Tests) ->
eval_tests(Config, fun check_test/2, Tests).
diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl
index e248934e10..e51c05a22c 100644
--- a/lib/stdlib/test/erl_expand_records_SUITE.erl
+++ b/lib/stdlib/test/erl_expand_records_SUITE.erl
@@ -107,8 +107,7 @@ attributes(doc) ->
attributes(suite) -> [];
attributes(Config) when is_list(Config) ->
Ts = [
- <<"-import(erl_expand_records_SUITE).
- -import(lists, [append/2, reverse/1]).
+ <<"-import(lists, [append/2, reverse/1]).
-record(r, {a,b}).
@@ -158,12 +157,12 @@ expr(Config) when is_list(Config) ->
2 = fun(X) -> X end(One + One),
3 = fun exprec_test:f/1(3),
4 = exprec_test:f(4),
- 5 = ''.f(5),
+ 5 = f(5),
L = receive
{a,message,L0} ->
L0
end,
- case catch a.b.c:foo(bar) of
+ case catch a:foo(bar) of
{'EXIT', _} -> ok
end,
_ = receive %Suppress warning.
@@ -263,8 +262,7 @@ pattern(doc) ->
pattern(suite) -> [];
pattern(Config) when is_list(Config) ->
Ts = [
- <<"-import(erl_expand_records_SUITE).
- -import(lists, [append/2, reverse/1]).
+ <<"-import(lists, [append/2, reverse/1]).
-record(r, {a,b}).
@@ -292,10 +290,10 @@ pattern(Config) when is_list(Config) ->
21 = t(#r{a = #r{}}),
22 = t(2),
23 = t(#r{a = #r{}, b = b}),
- 24 = t(a.b.c),
+ 24 = t(abc),
ok.
- t(a.b.c) ->
+ t(abc) ->
24;
t($a) ->
2;
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 90a37f6441..774229fca9 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -1732,7 +1732,7 @@ otp_5362(Config) when is_list(Config) ->
{otp_5362_2,
<<"-export([inline/0]).
- -import(lists.foo, [a/1,b/1]). % b/1 is not used
+ -import(lists, [a/1,b/1]). % b/1 is not used
-compile([{inline,{inl,7}}]). % undefined
-compile([{inline,[{inl,17}]}]). % undefined
@@ -1764,7 +1764,7 @@ otp_5362(Config) when is_list(Config) ->
{6,erl_lint,{bad_inline,{inl,17}}},
{11,erl_lint,{undefined_function,{fipp,0}}},
{22,erl_lint,{bad_nowarn_unused_function,{and_not_used,2}}}],
- [{3,erl_lint,{unused_import,{{b,1},'lists.foo'}}},
+ [{3,erl_lint,{unused_import,{{b,1},lists}}},
{9,erl_lint,{unused_function,{foop,0}}},
{19,erl_lint,{unused_function,{not_used,0}}},
{23,erl_lint,{unused_function,{and_not_used,1}}}]}},
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 64853ca078..db416b03b0 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -40,7 +40,7 @@
init_per_testcase/2, end_per_testcase/2]).
-export([ func/1, call/1, recs/1, try_catch/1, if_then/1,
- receive_after/1, bits/1, head_tail/1, package/1,
+ receive_after/1, bits/1, head_tail/1,
cond1/1, block/1, case1/1, ops/1, messages/1,
old_mnemosyne_syntax/1,
import_export/1, misc_attrs/1,
@@ -48,7 +48,8 @@
neg_indent/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_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1,
+ otp_10302/1]).
%% Internal export.
-export([ehook/6]).
@@ -74,12 +75,12 @@ all() ->
groups() ->
[{expr, [],
[func, call, recs, try_catch, if_then, receive_after,
- bits, head_tail, package, cond1, block, case1, ops,
+ bits, head_tail, cond1, block, case1, ops,
messages, old_mnemosyne_syntax]},
{attributes, [], [misc_attrs, import_export]},
{tickets, [],
[otp_6321, otp_6911, otp_6914, otp_8150, otp_8238,
- otp_8473, otp_8522, otp_8567, otp_8664, otp_9147]}].
+ otp_8473, otp_8522, otp_8567, otp_8664, otp_9147, otp_10302]}].
init_per_suite(Config) ->
Config.
@@ -438,9 +439,6 @@ bits(Config) when is_list(Config) ->
?line ok = pp_expr(<<"<<{a,b}/binary>>">>),
?line ok = pp_expr(<<"<<{foo:bar(),b}/binary>>">>),
?line ok = pp_expr(<<"<<(foo:bar()):(foo:bar())/binary>>">>),
- ?line ok = pp_expr(<<"<<(foo.bar)/binary>>">>),
- ?line ok = pp_expr(<<"<<(foo.bar):all/binary>>">>),
- ?line ok = pp_expr(<<"<<(foo.bar):(foo.bar)/binary>>">>),
ok.
head_tail(suite) ->
@@ -462,17 +460,6 @@ head_tail(Config) when is_list(Config) ->
?line compile(Config, Ts),
ok.
-package(suite) ->
- [];
-package(Config) when is_list(Config) ->
- Ts = [{package_1,
- <<"t() -> a.b:foo().">>},
- {package_2,
- <<"t() -> .lists:sort([]).">>}
- ],
- ?line compile(Config, Ts),
- ok.
-
cond1(suite) ->
[];
cond1(Config) when is_list(Config) ->
@@ -614,13 +601,11 @@ misc_attrs(suite) ->
[];
misc_attrs(Config) when is_list(Config) ->
?line ok = pp_forms(<<"-module(m). ">>),
- ?line ok = pp_forms(<<"-module(m.p, [A,B]). ">>),
?line ok = pp_forms(<<"-module(m, [Aafjlksfjdlsjflsdfjlsdjflkdsfjlk,"
"Blsjfdlslfjsdf]). ">>),
?line ok = pp_forms(<<"-export([]). ">>),
?line ok = pp_forms(<<"-export([foo/2, bar/0]). ">>),
?line ok = pp_forms(<<"-export([bar/0]). ">>),
- ?line ok = pp_forms(<<"-import(.lists). ">>),
?line ok = pp_forms(<<"-import(lists, []). ">>),
?line ok = pp_forms(<<"-import(lists, [map/2]). ">>),
?line ok = pp_forms(<<"-import(lists, [map/2, foreach/2]). ">>),
@@ -634,8 +619,12 @@ misc_attrs(Config) when is_list(Config) ->
hook(suite) ->
[];
hook(Config) when is_list(Config) ->
+ F = fun(H) -> H end,
+ do_hook(F).
+
+do_hook(HookFun) ->
Lc = parse_expr(binary_to_list(<<"[X || X <- [1,2,3]].">>)),
- H = fun hook/4,
+ H = HookFun(fun hook/4),
Expr = {call,0,{atom,0,fff},[{foo,Lc},{foo,Lc},{foo,Lc}]},
EChars = lists:flatten(erl_pp:expr(Expr, 0, H)),
Call = {call,0,{atom,0,foo},[Lc]},
@@ -692,7 +681,7 @@ hook(Config) when is_list(Config) ->
GChars2 = erl_pp:guard(G2),
?line true = GChars =:= lists:flatten(GChars2),
- EH = {?MODULE, ehook, [foo,bar]},
+ EH = HookFun({?MODULE, ehook, [foo,bar]}),
XEChars = erl_pp:expr(Expr, -1, EH),
?line true = remove_indentation(EChars) =:= lists:flatten(XEChars),
XEChars2 = erl_pp:expr(Expr, EH),
@@ -1068,6 +1057,43 @@ otp_9147(Config) when is_list(Config) ->
string:tokens(binary_to_list(Bin), "\n")),
ok.
+otp_10302(doc) ->
+ "OTP-10302. Unicode characters scanner/parser.";
+otp_10302(suite) -> [];
+otp_10302(Config) when is_list(Config) ->
+ Ts = [{uni_1,
+ <<"t() -> <<(<<\"abc\\x{aaa}\">>):3/binary>>.">>}
+ ],
+ compile(Config, Ts),
+ ok = pp_expr(<<"$\\x{aaa}">>),
+ ok = pp_expr(<<"\"1\\x{aaa}\"">>),
+ ok = pp_expr(<<"<<<<\"hej\">>/binary>>">>),
+ ok = pp_expr(<<"<< <<\"1\\x{aaa}\">>/binary>>">>),
+
+ U = [{encoding,unicode}],
+
+ do_hook(fun(H) -> [{hook,H}] end),
+ do_hook(fun(H) -> [{hook,H}]++U end),
+
+ ok = pp_expr(<<"$\\x{aaa}">>, [{hook,fun hook/4}]),
+
+ Opts = [{hook, fun unicode_hook/4},{encoding,unicode}],
+ Lc = parse_expr("[X || X <- [\"\x{400}\",\"\xFF\"]]."),
+ Expr = {call,0,{atom,0,fff},[{foo,{foo,Lc}},{foo,{foo,Lc}}]},
+ EChars = lists:flatten(erl_pp:expr(Expr, 0, Opts)),
+ Call = {call,0,{atom,0,foo},[{call,0,{atom,0,foo},[Lc]}]},
+ Expr2 = {call,0,{atom,0,fff},[Call,Call]},
+ EChars2 = erl_pp:exprs([Expr2], U),
+ EChars = lists:flatten(EChars2),
+ [$\x{400},$\x{400}] = [C || C <- EChars, C > 255],
+
+ ok = pp_forms(<<"function() -> {\"\x{400}\",$\x{400}}. "/utf8>>, U),
+ ok = pp_forms("function() -> {\"\x{400}\",$\x{400}}. ", []),
+ ok.
+
+unicode_hook({foo,E}, I, P, H) ->
+ erl_pp:expr({call,0,{atom,0,foo},[E]}, I, P, H).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
compile(Config, Tests) ->
@@ -1137,9 +1163,11 @@ flat_expr(Expr) ->
pp_forms(Bin) ->
pp_forms(Bin, none).
-pp_forms(Bin, Hook) ->
- PP1 = (catch parse_and_pp_forms(binary_to_list(Bin), Hook)),
- PP2 = (catch parse_and_pp_forms(PP1, Hook)),
+pp_forms(Bin, Options) when is_binary(Bin) ->
+ pp_forms(to_list(Bin, Options), Options);
+pp_forms(List, Options) when is_list(List) ->
+ PP1 = (catch parse_and_pp_forms(List, Options)),
+ PP2 = (catch parse_and_pp_forms(PP1, Options)),
case PP1 =:= PP2 of % same line numbers
true ->
test_max_line(PP1);
@@ -1147,8 +1175,8 @@ pp_forms(Bin, Hook) ->
not_ok
end.
-parse_and_pp_forms(String, Hook) ->
- lists:append(lists:map(fun(AF) -> erl_pp:form(AF, Hook)
+parse_and_pp_forms(String, Options) ->
+ lists:append(lists:map(fun(AF) -> erl_pp:form(AF, Options)
end, parse_forms(String))).
parse_forms(Chars) ->
@@ -1158,7 +1186,7 @@ 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
+ case erl_scan:tokens(Cont0, String, Line, [unicode]) of
{done, {ok, Tokens, EndLine}, Chars} ->
{ok, Form} = erl_parse:parse_form(Tokens),
parse_forms2(Chars, [], EndLine, [Form | Forms]);
@@ -1174,10 +1202,12 @@ pp_expr(Bin) ->
pp_expr(Bin, none).
%% Final dot is added.
-pp_expr(Bin, Hook) ->
- PP1 = (catch parse_and_pp_expr(binary_to_list(Bin), 0, Hook)),
- PPneg = (catch parse_and_pp_expr(binary_to_list(Bin), -1, Hook)),
- PP2 = (catch parse_and_pp_expr(PPneg, 0, Hook)),
+pp_expr(Bin, Options) when is_binary(Bin) ->
+ pp_expr(to_list(Bin, Options), Options);
+pp_expr(List, Options) when is_list(List) ->
+ PP1 = (catch parse_and_pp_expr(List, 0, Options)),
+ PPneg = (catch parse_and_pp_expr(List, -1, Options)),
+ PP2 = (catch parse_and_pp_expr(PPneg, 0, Options)),
if
PP1 =:= PP2 -> % same line numbers
case
@@ -1192,15 +1222,24 @@ pp_expr(Bin, Hook) ->
not_ok
end.
-parse_and_pp_expr(String, Indent, Hook) ->
+parse_and_pp_expr(String, Indent, Options) ->
StringDot = lists:flatten(String) ++ ".",
- erl_pp:expr(parse_expr(StringDot), Indent, Hook).
+ erl_pp:expr(parse_expr(StringDot), Indent, Options).
parse_expr(Chars) ->
- {ok, Tokens, _} = erl_scan:string(Chars),
+ {ok, Tokens, _} = erl_scan:string(Chars, 1, [unicode]),
{ok, [Expr]} = erl_parse:parse_exprs(Tokens),
Expr.
+to_list(Bin, Options) when is_list(Options) ->
+ case proplists:get_value(encoding, Options) of
+ unicode -> unicode:characters_to_list(Bin);
+ encoding -> binary_to_list(Bin);
+ undefined -> binary_to_list(Bin)
+ end;
+to_list(Bin, _Hook) ->
+ binary_to_list(Bin).
+
test_new_line(String) ->
case string:chr(String, $\n) of
0 -> ok;
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index 4298b2c701..34e1b99abe 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,7 +21,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([ error_1/1, error_2/1, iso88591/1, otp_7810/1]).
+-export([ error_1/1, error_2/1, iso88591/1, otp_7810/1, otp_10302/1]).
-import(lists, [nth/2,flatten/1]).
-import(io_lib, [print/1]).
@@ -59,7 +60,7 @@ end_per_testcase(_Case, Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [{group, error}, iso88591, otp_7810].
+ [{group, error}, iso88591, otp_7810, otp_10302].
groups() ->
[{error, [], [error_1, error_2]}].
@@ -131,10 +132,10 @@ iso88591(Config) when is_list(Config) ->
?line ok =
case catch begin
%% Some atom and variable names
- V1s = [$�,$�,$�,$�],
- V2s = [$N,$�,$r],
- A1s = [$h,$�,$r],
- A2s = [$�,$r,$e],
+ V1s = [$Á,$á,$é,$ë],
+ V2s = [$N,$ä,$r],
+ A1s = [$h,$ä,$r],
+ A2s = [$ö,$r,$e],
%% Test parsing atom and variable characters.
{ok,Ts1,_} = erl_scan:string(V1s ++ " " ++ V2s ++
"\327" ++
@@ -214,8 +215,8 @@ atoms() ->
?line test_string("'a b'", [{atom,1,'a b'}]),
?line test_string("a", [{atom,1,a}]),
?line test_string("a@2", [{atom,1,a@2}]),
- ?line test_string([39,65,200,39], [{atom,1,'A�'}]),
- ?line test_string("�rlig �sten", [{atom,1,�rlig},{atom,1,�sten}]),
+ ?line test_string([39,65,200,39], [{atom,1,'AÈ'}]),
+ ?line test_string("ärlig östen", [{atom,1,ärlig},{atom,1,östen}]),
?line {ok,[{atom,_,'$a'}],{1,6}} =
erl_scan:string("'$\\a'", {1,1}),
?line test("'$\\a'"),
@@ -289,7 +290,7 @@ errors() ->
?line {error,{1,erl_scan,{string,$","str"}},1} = %"
erl_scan:string("\"str"), %"
?line {error,{1,erl_scan,char},1} = erl_scan:string("$"),
- ?line test_string([34,65,200,34], [{string,1,"A�"}]),
+ ?line test_string([34,65,200,34], [{string,1,"AÈ"}]),
?line test_string("\\", [{'\\',1}]),
?line {'EXIT',_} =
(catch {foo, erl_scan:string('$\\a', {1,1})}), % type error
@@ -354,7 +355,7 @@ dots() ->
{".\n", {ok,[{dot,1}],2}},
{".%", {ok,[{dot,1}],1}},
{".\210",{ok,[{dot,1}],1}},
- {".% �h",{ok,[{dot,1}],1}},
+ {".% öh",{ok,[{dot,1}],1}},
{".%\n", {ok,[{dot,1}],2}},
{".$", {error,{1,erl_scan,char},1}},
{".$\\", {error,{1,erl_scan,char},1}},
@@ -369,7 +370,7 @@ dots() ->
?line [{column,1},{length,1},{line,1},{text,"."}] =
erl_scan:token_info(T2, [column, length, line, text]),
?line {ok,[{dot,_}=T3],{1,6}} =
- erl_scan:string(".% �h", {1,1}, text),
+ erl_scan:string(".% öh", {1,1}, text),
?line [{column,1},{length,1},{line,1},{text,"."}] =
erl_scan:token_info(T3, [column, length, line, text]),
?line {error,{{1,2},erl_scan,char},{1,3}} =
@@ -472,11 +473,11 @@ chars() ->
variables() ->
- ?line test_string(" \237_Aou�eiy��", [{var,1,'_Aou�eiy��'}]),
+ ?line test_string(" \237_Aouåeiyäö", [{var,1,'_Aouåeiyäö'}]),
?line test_string("A_b_c@", [{var,1,'A_b_c@'}]),
?line test_string("V@2", [{var,1,'V@2'}]),
- ?line test_string("ABD�", [{var,1,'ABD�'}]),
- ?line test_string("�rlig �sten", [{var,1,'�rlig'},{var,1,'�sten'}]),
+ ?line test_string("ABDÀ", [{var,1,'ABDÀ'}]),
+ ?line test_string("Ärlig Östen", [{var,1,'Ärlig'},{var,1,'Östen'}]),
ok.
eof() ->
@@ -823,7 +824,7 @@ unicode() ->
?line {ok,[{char,1,1}],1} = erl_scan:string([$$,$\\,$^,1089]),
?line {error,{1,erl_scan,Error},1} = erl_scan:string("\"qa\x{aaa}"),
- ?line "unterminated string starting with \"qa\\x{AAA}\"" =
+ ?line "unterminated string starting with \"qa"++[2730]++"\"" =
erl_scan:format_error(Error),
?line {error,{{1,1},erl_scan,_},{1,11}} =
erl_scan:string("\"qa\\x{aaa}",{1,1}),
@@ -887,9 +888,10 @@ unicode() ->
{char,_,$d},{']',_}],{1,8}} = erl_scan:string(Str1, {1,1}),
?line test(Str1),
Comment = "%% "++[1089],
- ?line {ok,[{comment,1,[$%,$%,$\s,1089]}],1} =
+ %% Returned a comment In R15B03:
+ {error,{1,erl_scan,{illegal,character}},1} =
erl_scan:string(Comment, 1, return),
- ?line {ok,[{comment,_,[$%,$%,$\s,1089]}],{1,5}} =
+ {error,{{1,1},erl_scan,{illegal,character}},{1,5}} =
erl_scan:string(Comment, {1,1}, return),
ok.
@@ -958,6 +960,182 @@ more_chars() ->
erl_scan:string("$\\xg", {1,1}),
ok.
+otp_10302(doc) ->
+ "OTP-10302. Unicode characters scanner/parser.";
+otp_10302(suite) ->
+ [];
+otp_10302(Config) when is_list(Config) ->
+ %% From unicode():
+ {error,{1,erl_scan,{illegal,atom}},1} =
+ erl_scan:string("'a"++[1089]++"b'", 1, unicode),
+ {error,{{1,1},erl_scan,{illegal,atom}},{1,12}} =
+ erl_scan:string("'qa\\x{aaa}'",{1,1},unicode),
+
+ {ok,[{char,1,1089}],1} = erl_scan:string([$$,1089], 1, unicode),
+ {ok,[{char,1,1089}],1} = erl_scan:string([$$,$\\,1089],1,unicode),
+
+ Qs = "$\\x{aaa}",
+ {ok,[{char,1,2730}],1} = erl_scan:string(Qs,1,unicode),
+ {ok,[Q2],{1,9}} = erl_scan:string(Qs,{1,1},[unicode,text]),
+ [{category,char},{column,1},{length,8},
+ {line,1},{symbol,16#aaa},{text,Qs}] =
+ erl_scan:token_info(Q2),
+
+ Tags = [category, column, length, line, symbol, text],
+
+ U1 = "\"\\x{aaa}\"",
+ {ok,[T1],{1,10}} = erl_scan:string(U1, {1,1}, [unicode,text]),
+ [{category,string},{column,1},{length,9},{line,1},
+ {symbol,[16#aaa]},{text,U1}] = erl_scan:token_info(T1, Tags),
+
+ U2 = "\"\\x41\\x{fff}\\x42\"",
+ {ok,[{string,1,[65,4095,66]}],1} = erl_scan:string(U2, 1, unicode),
+
+ U3 = "\"a\n\\x{fff}\n\"",
+ {ok,[{string,1,[97,10,4095,10]}],3} = erl_scan:string(U3, 1,unicode),
+
+ U4 = "\"\\^\n\\x{aaa}\\^\n\"",
+ {ok,[{string,1,[10,2730,10]}],3} = erl_scan:string(U4, 1,[unicode]),
+
+ Str1 = "\"ab" ++ [1089] ++ "cd\"",
+ {ok,[{string,1,[97,98,1089,99,100]}],1} =
+ erl_scan:string(Str1,1,unicode),
+ {ok,[{string,{1,1},[97,98,1089,99,100]}],{1,8}} =
+ erl_scan:string(Str1, {1,1},unicode),
+
+ OK1 = 16#D800-1,
+ OK2 = 16#DFFF+1,
+ OK3 = 16#FFFE-1,
+ OK4 = 16#FFFF+1,
+ OKL = [OK1,OK2,OK3,OK4],
+
+ Illegal1 = 16#D800,
+ Illegal2 = 16#DFFF,
+ Illegal3 = 16#FFFE,
+ Illegal4 = 16#FFFF,
+ IllegalL = [Illegal1,Illegal2,Illegal3,Illegal4],
+
+ [{ok,[{comment,1,[$%,$%,$\s,OK]}],1} =
+ erl_scan:string("%% "++[OK], 1, [unicode,return]) ||
+ OK <- OKL],
+ {ok,[{comment,_,[$%,$%,$\s,OK1]}],{1,5}} =
+ erl_scan:string("%% "++[OK1], {1,1}, [unicode,return]),
+ [{error,{1,erl_scan,{illegal,character}},1} =
+ erl_scan:string("%% "++[Illegal], 1, [unicode,return]) ||
+ Illegal <- IllegalL],
+ {error,{{1,1},erl_scan,{illegal,character}},{1,5}} =
+ erl_scan:string("%% "++[Illegal1], {1,1}, [unicode,return]),
+
+ [{ok,[],1} = erl_scan:string("%% "++[OK], 1, [unicode]) ||
+ OK <- OKL],
+ {ok,[],{1,5}} = erl_scan:string("%% "++[OK1], {1,1}, [unicode]),
+ [{error,{1,erl_scan,{illegal,character}},1} =
+ erl_scan:string("%% "++[Illegal], 1, [unicode]) ||
+ Illegal <- IllegalL],
+ {error,{{1,1},erl_scan,{illegal,character}},{1,5}} =
+ erl_scan:string("%% "++[Illegal1], {1,1}, [unicode]),
+
+ [{ok,[{string,{1,1},[OK]}],{1,4}} =
+ erl_scan:string("\""++[OK]++"\"",{1,1},unicode) ||
+ OK <- OKL],
+ [{error,{{1,2},erl_scan,{illegal,character}},{1,3}} =
+ erl_scan:string("\""++[OK]++"\"",{1,1},unicode) ||
+ OK <- IllegalL],
+
+ [{error,{{1,1},erl_scan,{illegal,character}},{1,2}} =
+ erl_scan:string([Illegal],{1,1},unicode) ||
+ Illegal <- IllegalL],
+
+ {ok,[{char,{1,1},OK1}],{1,3}} =
+ erl_scan:string([$$,OK1],{1,1},unicode),
+ {error,{{1,1},erl_scan,{illegal,character}},{1,2}} =
+ erl_scan:string([$$,Illegal1],{1,1},unicode),
+
+ {ok,[{char,{1,1},OK1}],{1,4}} =
+ erl_scan:string([$$,$\\,OK1],{1,1},unicode),
+ {error,{{1,1},erl_scan,{illegal,character}},{1,4}} =
+ erl_scan:string([$$,$\\,Illegal1],{1,1},unicode),
+
+ {ok,[{string,{1,1},[55295]}],{1,5}} =
+ erl_scan:string("\"\\"++[OK1]++"\"",{1,1},unicode),
+ {error,{{1,2},erl_scan,{illegal,character}},{1,4}} =
+ erl_scan:string("\"\\"++[Illegal1]++"\"",{1,1},unicode),
+
+ {ok,[{char,{1,1},OK1}],{1,10}} =
+ erl_scan:string("$\\x{D7FF}",{1,1},unicode),
+ {error,{{1,1},erl_scan,{illegal,character}},{1,10}} =
+ erl_scan:string("$\\x{D800}",{1,1},unicode),
+
+ %% Not erl_scan, but erl_parse.
+ {integer,0,1} = erl_parse:abstract(1),
+ Float = 3.14, {float,0,Float} = erl_parse:abstract(Float),
+ {nil,0} = erl_parse:abstract([]),
+ {bin,0,
+ [{bin_element,0,{integer,0,1},default,default},
+ {bin_element,0,{integer,0,2},default,default}]} =
+ erl_parse:abstract(<<1,2>>),
+ {cons,0,{tuple,0,[{atom,0,a}]},{atom,0,b}} =
+ erl_parse:abstract([{a} | b]),
+ {string,0,"str"} = erl_parse:abstract("str"),
+ {cons,0,
+ {integer,0,$a},
+ {cons,0,{integer,0,1024},{string,0,"c"}}} =
+ erl_parse:abstract("a"++[1024]++"c"),
+
+ Line = 17,
+ {integer,Line,1} = erl_parse:abstract(1, Line),
+ Float = 3.14, {float,Line,Float} = erl_parse:abstract(Float, Line),
+ {nil,Line} = erl_parse:abstract([], Line),
+ {bin,Line,
+ [{bin_element,Line,{integer,Line,1},default,default},
+ {bin_element,Line,{integer,Line,2},default,default}]} =
+ erl_parse:abstract(<<1,2>>, Line),
+ {cons,Line,{tuple,Line,[{atom,Line,a}]},{atom,Line,b}} =
+ erl_parse:abstract([{a} | b], Line),
+ {string,Line,"str"} = erl_parse:abstract("str", Line),
+ {cons,Line,
+ {integer,Line,$a},
+ {cons,Line,{integer,Line,1024},{string,Line,"c"}}} =
+ erl_parse:abstract("a"++[1024]++"c", Line),
+
+ Opts1 = [{line,17}],
+ {integer,Line,1} = erl_parse:abstract(1, Opts1),
+ Float = 3.14, {float,Line,Float} = erl_parse:abstract(Float, Opts1),
+ {nil,Line} = erl_parse:abstract([], Opts1),
+ {bin,Line,
+ [{bin_element,Line,{integer,Line,1},default,default},
+ {bin_element,Line,{integer,Line,2},default,default}]} =
+ erl_parse:abstract(<<1,2>>, Opts1),
+ {cons,Line,{tuple,Line,[{atom,Line,a}]},{atom,Line,b}} =
+ erl_parse:abstract([{a} | b], Opts1),
+ {string,Line,"str"} = erl_parse:abstract("str", Opts1),
+ {cons,Line,
+ {integer,Line,$a},
+ {cons,Line,{integer,Line,1024},{string,Line,"c"}}} =
+ erl_parse:abstract("a"++[1024]++"c", Opts1),
+
+ [begin
+ {integer,Line,1} = erl_parse:abstract(1, Opts2),
+ Float = 3.14, {float,Line,Float} = erl_parse:abstract(Float, Opts2),
+ {nil,Line} = erl_parse:abstract([], Opts2),
+ {bin,Line,
+ [{bin_element,Line,{integer,Line,1},default,default},
+ {bin_element,Line,{integer,Line,2},default,default}]} =
+ erl_parse:abstract(<<1,2>>, Opts2),
+ {cons,Line,{tuple,Line,[{atom,Line,a}]},{atom,Line,b}} =
+ erl_parse:abstract([{a} | b], Opts2),
+ {string,Line,"str"} = erl_parse:abstract("str", Opts2),
+ {string,Line,[97,1024,99]} =
+ erl_parse:abstract("a"++[1024]++"c", Opts2)
+ end || Opts2 <- [[{encoding,unicode},{line,Line}],
+ [{encoding,utf8},{line,Line}]]],
+
+ {cons,0,
+ {integer,0,97},
+ {cons,0,{integer,0,1024},{string,0,"c"}}} =
+ erl_parse:abstract("a"++[1024]++"c", [{encoding,latin1}]),
+ ok.
+
test_string(String, Expected) ->
{ok, Expected, _End} = erl_scan:string(String),
test(String).
diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl
index 5b592c65cc..7634c21a17 100644
--- a/lib/stdlib/test/escript_SUITE.erl
+++ b/lib/stdlib/test/escript_SUITE.erl
@@ -34,7 +34,8 @@
create_and_extract/1,
foldl/1,
overflow/1,
- verify_sections/3
+ verify_sections/3,
+ unicode/1
]).
-include_lib("test_server/include/test_server.hrl").
@@ -46,7 +47,7 @@ all() ->
[basic, errors, strange_name, emulator_flags,
module_script, beam_script, archive_script, epp,
create_and_extract, foldl, overflow,
- archive_script_file_access].
+ archive_script_file_access, unicode].
groups() ->
[].
@@ -810,6 +811,8 @@ normalize_sections(Sections) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
foldl(Config) when is_list(Config) ->
{NewFile, _FileInfo,
_EmuArg, _Source,
@@ -887,6 +890,20 @@ emulate_escript_foldl(Fun, Acc, File) ->
{error, Reason}
end.
+unicode(Config) when is_list(Config) ->
+ Data = ?config(data_dir, Config),
+ Dir = filename:absname(Data), %Get rid of trailing slash.
+ run(Dir, "unicode1",
+ [<<"escript: exception error: an error occurred when evaluating"
+ " an arithmetic expression\n in operator '/'/2\n "
+ "called as <<170>> / <<170>>\nExitCode:127">>]),
+ run(Dir, "unicode2",
+ [<<"escript: exception error: an error occurred when evaluating"
+ " an arithmetic expression\n in operator '/'/2\n "
+ "called as <<\"\xaa\">> / <<\"\xaa\">>\nExitCode:127">>]),
+ run(Dir, "unicode3", [<<"ExitCode:0">>]),
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
overflow(Config) when is_list(Config) ->
diff --git a/lib/stdlib/test/escript_SUITE_data/unicode1 b/lib/stdlib/test/escript_SUITE_data/unicode1
new file mode 100755
index 0000000000..a77574625e
--- /dev/null
+++ b/lib/stdlib/test/escript_SUITE_data/unicode1
@@ -0,0 +1,14 @@
+#!/usr/bin/env escript
+%% -*- erlang -*-
+
+-export([main/1]).
+
+main(_) ->
+ ok = io:setopts([{encoding,unicode}]),
+ _D = erlang:system_flag(backtrace_depth, 0),
+ A = <<"\x{aa}">>,
+ S = lists:flatten(io_lib:format("~p/~p.", [A, A])),
+ {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Es} = erl_parse:parse_exprs(Ts),
+ B = erl_eval:new_bindings(),
+ erl_eval:exprs(Es, B).
diff --git a/lib/stdlib/test/escript_SUITE_data/unicode2 b/lib/stdlib/test/escript_SUITE_data/unicode2
new file mode 100755
index 0000000000..495188f6f0
--- /dev/null
+++ b/lib/stdlib/test/escript_SUITE_data/unicode2
@@ -0,0 +1,14 @@
+#!/usr/bin/env escript
+%% -*- erlang -*-
+
+-export([main/1]).
+
+main(_) ->
+ ok = io:setopts([{encoding,latin1}]),
+ _D = erlang:system_flag(backtrace_depth, 0),
+ A = <<"\x{aa}">>,
+ S = lists:flatten(io_lib:format("~p/~p.", [A, A])),
+ {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Es} = erl_parse:parse_exprs(Ts),
+ B = erl_eval:new_bindings(),
+ erl_eval:exprs(Es, B).
diff --git a/lib/stdlib/test/escript_SUITE_data/unicode3 b/lib/stdlib/test/escript_SUITE_data/unicode3
new file mode 100755
index 0000000000..944487dcae
--- /dev/null
+++ b/lib/stdlib/test/escript_SUITE_data/unicode3
@@ -0,0 +1,13 @@
+#!/usr/bin/env escript
+%% -*- erlang; coding: utf-8 -*-
+
+-export([main/1]).
+
+main(_) ->
+ ok = io:setopts([{encoding,unicode}]),
+ Bin1 = <<"örn_Ѐ שלום-שלום+של 日本語">>,
+
+ L = [246,114,110,95,1024,32,1513,1500,1493,1501,45,1513,1500,1493,
+ 1501,43,1513,1500,32,26085,26412,35486],
+ L = unicode:characters_to_list(Bin1, utf8),
+ ok.
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 74fcdcc7d2..521d7255ea 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,7 +29,7 @@
manpage/1, otp_6708/1, otp_7084/1, otp_7421/1,
io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1,
io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1,
- io_lib_print_binary_depth_one/1]).
+ io_lib_print_binary_depth_one/1, otp_10302/1]).
%-define(debug, true).
@@ -64,7 +65,7 @@ all() ->
manpage, otp_6708, otp_7084, otp_7421,
io_lib_collect_line_3_wb, cr_whitespace_in_string,
io_fread_newlines, otp_8989, io_lib_fread_literal,
- io_lib_print_binary_depth_one].
+ io_lib_print_binary_depth_one, otp_10302].
groups() ->
[].
@@ -894,7 +895,7 @@ otp_6354(Config) when is_list(Config) ->
?line "\"\\b\\t\\n\\v\\f\\r\\e\250\"" =
p([8,9,10,11,12,13,27,168], 1, 40, -1),
% ?line "\"\\b\\t\\n\"\n \"\\v\\f\\r\"\n \"\\e\250\"" =
- ?line "\"\\b\\t\\n\\v\\f\\r\\e�\"" =
+ ?line "\"\\b\\t\\n\\v\\f\\r\\e¨\"" =
p([8,9,10,11,12,13,27,168], 1, 10, -1),
?line "\"\\b\\t\\n\\v\\f\\r\\e\250\"" =
p([8,9,10,11,12,13,27,168], 1, 40, 100),
@@ -2034,3 +2035,44 @@ io_lib_print_binary_depth_one(Suite) when is_list(Suite) ->
?line "<<...>>" = fmt("~W", [<<1:7>>, 1]),
?line "<<...>>" = fmt("~P", [<<1:7>>, 1]),
ok.
+
+otp_10302(doc) ->
+ "OTP-10302. Unicode";
+otp_10302(Suite) when is_list(Suite) ->
+ "\"\x{400}\"" = pretty("\x{400}", -1),
+ "<<\"\x{400}\"/utf8>>" = pretty(<<"\x{400}"/utf8>>, -1),
+
+ "<<\"\x{400}foo\"/utf8>>" = pretty(<<"\x{400}foo"/utf8>>, 2),
+ "<<\"äppl\"/utf8>>" = pretty(<<"äppl"/utf8>>, 2),
+ "<<\"äppl\"/utf8...>>" = pretty(<<"äpple"/utf8>>, 2),
+ "<<\"apel\">>" = pretty(<<"apel">>, 2),
+ "<<\"apel\"...>>" = pretty(<<"apelsin">>, 2),
+ "<<228,112,112,108>>" = fmt("~tp", [<<"äppl">>]),
+ "<<228,...>>" = fmt("~tP", [<<"äppl">>, 2]),
+
+ Chars = lists:seq(0, 512), % just a few...
+ [] = [C || C <- Chars, S <- io_lib:write_unicode_char_as_latin1(C),
+ not is_latin1(S)],
+ L1 = [S || C <- Chars, S <- io_lib:write_unicode_char(C),
+ not is_latin1(S)],
+ L1 = lists:seq(256, 512),
+
+ [] = [C || C <- Chars, S <- io_lib:write_unicode_string_as_latin1([C]),
+ not is_latin1(S)],
+ L2 = [S || C <- Chars, S <- io_lib:write_unicode_string([C]),
+ not is_latin1(S)],
+ L2 = lists:seq(256, 512),
+
+ ok.
+
+pretty(Term, Depth) when is_integer(Depth) ->
+ Opts = [{column, 1}, {line_length, 20},
+ {depth, Depth}, {max_chars, 60},
+ {encoding, unicode}],
+ pretty(Term, Opts);
+pretty(Term, Opts) when is_list(Opts) ->
+ R = io_lib_pretty:print(Term, Opts),
+ lists:flatten(io_lib:format("~ts", [R])).
+
+is_latin1(S) ->
+ S >= 0 andalso S =< 255.
diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl
index 17e69f7c1c..299daf0e42 100644
--- a/lib/stdlib/test/io_proto_SUITE.erl
+++ b/lib/stdlib/test/io_proto_SUITE.erl
@@ -736,7 +736,7 @@ binary_options(Config) when is_list(Config) ->
{getline_re, ".*<<\"hej\\\\n\">>"},
{putline, "io:get_line('')."},
{putline, binary_to_list(<<"\345\344\366"/utf8>>)},
- {getline_re, ".*<<\""++binary_to_list(unicode:characters_to_binary(<<"\345\344\366"/utf8>>,latin1,utf8))++"\\\\n\">>"}
+ {getline_re, ".*<<\""++binary_to_list(<<"\345\344\366"/utf8>>)++"\\\\n\"/utf8>>"}
],[],[],"-oldshell"),
ok.
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index e3090e4a47..cac8309bd9 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -6062,21 +6062,6 @@ otp_6673(Config) when is_list(Config) ->
],
?line run(Config, Ts_RT),
- %% Ulf Wiger provided a patch that makes QLC work with packages:
- Dir = filename:join(?privdir, "p"),
- ?line ok = filelib:ensure_dir(filename:join(Dir, ".")),
- File = filename:join(Dir, "p.erl"),
- ?line ok = file:write_file(File,
- <<"-module(p.p).\n"
- "-export([q/0]).\n"
- "-include_lib(\"stdlib/include/qlc.hrl\").\n"
- "q() ->\n"
- " .qlc:q([X || X <- [1,2]]).">>),
- ?line {ok, 'p.p'} = compile:file(File, [{outdir,Dir}]),
- ?line code:purge('p.p'),
- ?line {module, 'p.p'} = code:load_abs(filename:rootname(File), 'p.p'),
- ?line [1,2] = qlc:e(p.p:q()),
-
ok.
otp_6964(doc) ->
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index 8ee0a13f4c..500f5fadb9 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -291,10 +292,10 @@ global_capture(Config) when is_list(Config) ->
?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,index}]),
?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,binary}]),
?line match = re:run("ABCabcdABCabcdA","a(?<FOO>bcd)",[global,{capture,none,list}]),
- ?line {match,[[<<195,133,98,99,100>>,<<"bcd">>],[<<"abcd">>,<<"bcd">>]]} = re:run("ABC�bcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,binary},unicode]),
- ?line {match,[["�bcd","bcd"],["abcd","bcd"]]} = re:run(<<"ABC",8#303,8#205,"bcdABCabcdA">>,".(?<FOO>bcd)",[global,{capture,all,list},unicode]),
- ?line {match,[["�bcd","bcd"],["abcd","bcd"]]} = re:run("ABC�bcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,list},unicode]),
- ?line {match,[[{3,5},{5,3}],[{11,4},{12,3}]]} = re:run("ABC�bcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,index},unicode]),
+ ?line {match,[[<<195,133,98,99,100>>,<<"bcd">>],[<<"abcd">>,<<"bcd">>]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,binary},unicode]),
+ ?line {match,[["Åbcd","bcd"],["abcd","bcd"]]} = re:run(<<"ABC",8#303,8#205,"bcdABCabcdA">>,".(?<FOO>bcd)",[global,{capture,all,list},unicode]),
+ ?line {match,[["Åbcd","bcd"],["abcd","bcd"]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,list},unicode]),
+ ?line {match,[[{3,5},{5,3}],[{11,4},{12,3}]]} = re:run("ABCÅbcdABCabcdA",".(?<FOO>bcd)",[global,{capture,all,index},unicode]),
?t:timetrap_cancel(Dog),
ok.
@@ -314,17 +315,17 @@ replace_return(Config) when is_list(Config) ->
Dog = ?t:timetrap(?t:minutes(3)),
?line {'EXIT',{badarg,_}} = (catch re:replace("na","(a","")),
?line <<"nasse">> = re:replace(<<"nisse">>,"i","a",[{return,binary}]),
- ?line <<"ABC�XABCXA">> = re:replace("ABC\305abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary}]),
+ ?line <<"ABCÅXABCXA">> = re:replace("ABC\305abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary}]),
- ?line [<<"ABC�">>,
+ ?line [<<"ABCÅ">>,
<<"X">>,
<<"ABC">>,
<<"X">> |
<<"A">> ] =
- re:replace("ABC�abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,iodata}]),
- ?line "ABC�XABCXA" = re:replace("ABC�abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,list},unicode]),
- ?line <<65,66,67,195,133,88,65,66,67,88,65>> = re:replace("ABC�abcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary},unicode]),
- ?line <<65,66,67,195,133,88,65,66,67,97,98,99,100,65>> = re:replace("ABC�abcdABCabcdA","a(?<FOO>bcd)","X",[{return,binary},unicode]),
+ re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,iodata}]),
+ ?line "ABCÅXABCXA" = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,list},unicode]),
+ ?line <<65,66,67,195,133,88,65,66,67,88,65>> = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[global,{return,binary},unicode]),
+ ?line <<65,66,67,195,133,88,65,66,67,97,98,99,100,65>> = re:replace("ABCÅabcdABCabcdA","a(?<FOO>bcd)","X",[{return,binary},unicode]),
?line <<"iXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\9X",[{return,binary}]),
?line <<"jXk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\10X",[{return,binary}]),
?line <<"Xk">> = re:replace("abcdefghijk","(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)","\\11X",[{return,binary}]),
diff --git a/lib/stdlib/test/re_testoutput1_replacement_test.erl b/lib/stdlib/test/re_testoutput1_replacement_test.erl
index 69cb140e0d..8f8d8762ad 100644
--- a/lib/stdlib/test/re_testoutput1_replacement_test.erl
+++ b/lib/stdlib/test/re_testoutput1_replacement_test.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -274,10 +275,10 @@ run() ->
?line <<"dthing">> = iolist_to_binary(re:replace("dthing","^[^]cde]","y\\1I&MoqRPG&GQa\\1l",[global])),
?line <<"ething">> = iolist_to_binary(re:replace("ething","^[^]cde]","AsxwUn\\1GqkWNdgRJk",[])),
?line <<"ething">> = iolist_to_binary(re:replace("ething","^[^]cde]","AsxwUn\\1GqkWNdgRJk",[global])),
-?line <<"RornKmOnaFr�tWgtW">> = iolist_to_binary(re:replace("�","^\\�","R\\1o\\1r\\1nKmOnaFr&tWgtW",[])),
-?line <<"RornKmOnaFr�tWgtW">> = iolist_to_binary(re:replace("�","^\\�","R\\1o\\1r\\1nKmOnaFr&tWgtW",[global])),
-?line <<"ufbmbfOYuK�wf�E�dx">> = iolist_to_binary(re:replace("�","^�","ufbmbfOYuK&wf&E&\\1dx",[])),
-?line <<"ufbmbfOYuK�wf�E�dx">> = iolist_to_binary(re:replace("�","^�","ufbmbfOYuK&wf&E&\\1dx",[global])),
+?line <<"RornKmOnaFrtWgtW">> = iolist_to_binary(re:replace("","^\\","R\\1o\\1r\\1nKmOnaFr&tWgtW",[])),
+?line <<"RornKmOnaFrtWgtW">> = iolist_to_binary(re:replace("","^\\","R\\1o\\1r\\1nKmOnaFr&tWgtW",[global])),
+?line <<"ufbmbfOYuKÿwfÿEÿdx">> = iolist_to_binary(re:replace("ÿ","^ÿ","ufbmbfOYuK&wf&E&\\1dx",[])),
+?line <<"ufbmbfOYuKÿwfÿEÿdx">> = iolist_to_binary(re:replace("ÿ","^ÿ","ufbmbfOYuK&wf&E&\\1dx",[global])),
?line <<"oAdJme0jw">> = iolist_to_binary(re:replace("0","^[0-9]+$","oAdJme\\1&jw",[])),
?line <<"oAdJme0jw">> = iolist_to_binary(re:replace("0","^[0-9]+$","oAdJme\\1&jw",[global])),
?line <<"1aoKN">> = iolist_to_binary(re:replace("1","^[0-9]+$","&aoKN",[])),
@@ -14972,10 +14973,10 @@ def">> = iolist_to_binary(re:replace("abc
def","abc$","M",[global])),
?line <<"abcWCabcSYXGPjRugTabcVGabcSX">> = iolist_to_binary(re:replace("abcS","(abc)\\123","\\1WC&YXGPjRugT\\1VG&X",[])),
?line <<"abcWCabcSYXGPjRugTabcVGabcSX">> = iolist_to_binary(re:replace("abcS","(abc)\\123","\\1WC&YXGPjRugT\\1VG&X",[global])),
-?line <<"fabc�Uabc�UmiqabceCsabcabc�">> = iolist_to_binary(re:replace("abc�","(abc)\\223","f&U&Umiq\\1eCs\\1&",[])),
-?line <<"fabc�Uabc�UmiqabceCsabcabc�">> = iolist_to_binary(re:replace("abc�","(abc)\\223","f&U&Umiq\\1eCs\\1&",[global])),
-?line <<"JRFabcxnbabc�Vkabc�fWigQMuaY">> = iolist_to_binary(re:replace("abc�","(abc)\\323","JRF\\1xnb&Vk&fWigQMuaY",[])),
-?line <<"JRFabcxnbabc�Vkabc�fWigQMuaY">> = iolist_to_binary(re:replace("abc�","(abc)\\323","JRF\\1xnb&Vk&fWigQMuaY",[global])),
+?line <<"fabc“Uabc“UmiqabceCsabcabc“">> = iolist_to_binary(re:replace("abc“","(abc)\\223","f&U&Umiq\\1eCs\\1&",[])),
+?line <<"fabc“Uabc“UmiqabceCsabcabc“">> = iolist_to_binary(re:replace("abc“","(abc)\\223","f&U&Umiq\\1eCs\\1&",[global])),
+?line <<"JRFabcxnbabcÓVkabcÓfWigQMuaY">> = iolist_to_binary(re:replace("abcÓ","(abc)\\323","JRF\\1xnb&Vk&fWigQMuaY",[])),
+?line <<"JRFabcxnbabcÓVkabcÓfWigQMuaY">> = iolist_to_binary(re:replace("abcÓ","(abc)\\323","JRF\\1xnb&Vk&fWigQMuaY",[global])),
?line <<"vgabc@QQ">> = iolist_to_binary(re:replace("abc@","(abc)\\100","vg&QQ",[])),
?line <<"vgabc@QQ">> = iolist_to_binary(re:replace("abc@","(abc)\\100","vg&QQ",[global])),
?line <<"abc@OkvNytabc@abcabc@a">> = iolist_to_binary(re:replace("abc@","(abc)\\100","&OkvNyt&\\1&a",[])),
@@ -18343,24 +18344,24 @@ xb","(?!^)x","\\1tysI\\1v\\1BVwx\\1FOWG\\1&C",[multiline,
?line <<"cY">> = iolist_to_binary(re:replace("M","\\M","cY\\1",[global])),
?line <<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">> = iolist_to_binary(re:replace("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","(a+)*b","yWOTIFhIX\\1H",[])),
?line <<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">> = iolist_to_binary(re:replace("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","(a+)*b","yWOTIFhIX\\1H",[global])),
-?line <<"NREGularsRREGularWEYrVRr">> = iolist_to_binary(re:replace("REGular","(?i)reg(?:ul(?:[a�]|ae)r|ex)","N&\\1sR&WEYrVRr",[])),
-?line <<"NREGularsRREGularWEYrVRr">> = iolist_to_binary(re:replace("REGular","(?i)reg(?:ul(?:[a�]|ae)r|ex)","N&\\1sR&WEYrVRr",[global])),
-?line <<"G">> = iolist_to_binary(re:replace("regulaer","(?i)reg(?:ul(?:[a�]|ae)r|ex)","G",[])),
-?line <<"G">> = iolist_to_binary(re:replace("regulaer","(?i)reg(?:ul(?:[a�]|ae)r|ex)","G",[global])),
-?line <<"PSsXtwlmy">> = iolist_to_binary(re:replace("Regex","(?i)reg(?:ul(?:[a�]|ae)r|ex)","PSsXtwlmy",[])),
-?line <<"PSsXtwlmy">> = iolist_to_binary(re:replace("Regex","(?i)reg(?:ul(?:[a�]|ae)r|ex)","PSsXtwlmy",[global])),
-?line <<"regul�rmiYTi">> = iolist_to_binary(re:replace("regul�r","(?i)reg(?:ul(?:[a�]|ae)r|ex)","&miYTi\\1\\1",[])),
-?line <<"regul�rmiYTi">> = iolist_to_binary(re:replace("regul�r","(?i)reg(?:ul(?:[a�]|ae)r|ex)","&miYTi\\1\\1",[global])),
-?line <<"W�����rxh�����yUoaLOIegmSA">> = iolist_to_binary(re:replace("�����","����[�-��-�]+","W&rxh&yUoaL\\1OIegmS\\1A",[])),
-?line <<"W�����rxh�����yUoaLOIegmSA">> = iolist_to_binary(re:replace("�����","����[�-��-�]+","W&rxh&yUoaL\\1OIegmS\\1A",[global])),
-?line <<"F�����gnWPyHeh�����tXTQ">> = iolist_to_binary(re:replace("�����","����[�-��-�]+","F&gnWPyHe\\1h&tXTQ",[])),
-?line <<"F�����gnWPyHeh�����tXTQ">> = iolist_to_binary(re:replace("�����","����[�-��-�]+","F&gnWPyHe\\1h&tXTQ",[global])),
-?line <<"sHerHnAhAdx">> = iolist_to_binary(re:replace("�����","����[�-��-�]+","sHer\\1HnA\\1h\\1Adx",[])),
-?line <<"sHerHnAhAdx">> = iolist_to_binary(re:replace("�����","����[�-��-�]+","sHer\\1HnA\\1h\\1Adx",[global])),
-?line <<"trobAQoU�����n">> = iolist_to_binary(re:replace("�����","����[�-��-�]+","tr\\1obAQoU&n",[])),
-?line <<"trobAQoU�����n">> = iolist_to_binary(re:replace("�����","����[�-��-�]+","tr\\1obAQoU&n",[global])),
-?line <<"�XAZSd">> = iolist_to_binary(re:replace("�XAZXB","(?<=Z)X.","Sd",[])),
-?line <<"�XAZSd">> = iolist_to_binary(re:replace("�XAZXB","(?<=Z)X.","Sd",[global])),
+?line <<"NREGularsRREGularWEYrVRr">> = iolist_to_binary(re:replace("REGular","(?i)reg(?:ul(?:[aä]|ae)r|ex)","N&\\1sR&WEYrVRr",[])),
+?line <<"NREGularsRREGularWEYrVRr">> = iolist_to_binary(re:replace("REGular","(?i)reg(?:ul(?:[aä]|ae)r|ex)","N&\\1sR&WEYrVRr",[global])),
+?line <<"G">> = iolist_to_binary(re:replace("regulaer","(?i)reg(?:ul(?:[aä]|ae)r|ex)","G",[])),
+?line <<"G">> = iolist_to_binary(re:replace("regulaer","(?i)reg(?:ul(?:[aä]|ae)r|ex)","G",[global])),
+?line <<"PSsXtwlmy">> = iolist_to_binary(re:replace("Regex","(?i)reg(?:ul(?:[aä]|ae)r|ex)","PSsXtwlmy",[])),
+?line <<"PSsXtwlmy">> = iolist_to_binary(re:replace("Regex","(?i)reg(?:ul(?:[aä]|ae)r|ex)","PSsXtwlmy",[global])),
+?line <<"regulärmiYTi">> = iolist_to_binary(re:replace("regulär","(?i)reg(?:ul(?:[aä]|ae)r|ex)","&miYTi\\1\\1",[])),
+?line <<"regulärmiYTi">> = iolist_to_binary(re:replace("regulär","(?i)reg(?:ul(?:[aä]|ae)r|ex)","&miYTi\\1\\1",[global])),
+?line <<"WÅæåäàrxhÅæåäàyUoaLOIegmSA">> = iolist_to_binary(re:replace("Åæåäà","Åæåä[à-ÿÀ-ß]+","W&rxh&yUoaL\\1OIegmS\\1A",[])),
+?line <<"WÅæåäàrxhÅæåäàyUoaLOIegmSA">> = iolist_to_binary(re:replace("Åæåäà","Åæåä[à-ÿÀ-ß]+","W&rxh&yUoaL\\1OIegmS\\1A",[global])),
+?line <<"FÅæåäÿgnWPyHehÅæåäÿtXTQ">> = iolist_to_binary(re:replace("Åæåäÿ","Åæåä[à-ÿÀ-ß]+","F&gnWPyHe\\1h&tXTQ",[])),
+?line <<"FÅæåäÿgnWPyHehÅæåäÿtXTQ">> = iolist_to_binary(re:replace("Åæåäÿ","Åæåä[à-ÿÀ-ß]+","F&gnWPyHe\\1h&tXTQ",[global])),
+?line <<"sHerHnAhAdx">> = iolist_to_binary(re:replace("ÅæåäÀ","Åæåä[à-ÿÀ-ß]+","sHer\\1HnA\\1h\\1Adx",[])),
+?line <<"sHerHnAhAdx">> = iolist_to_binary(re:replace("ÅæåäÀ","Åæåä[à-ÿÀ-ß]+","sHer\\1HnA\\1h\\1Adx",[global])),
+?line <<"trobAQoUÅæåäßn">> = iolist_to_binary(re:replace("Åæåäß","Åæåä[à-ÿÀ-ß]+","tr\\1obAQoU&n",[])),
+?line <<"trobAQoUÅæåäßn">> = iolist_to_binary(re:replace("Åæåäß","Åæåä[à-ÿÀ-ß]+","tr\\1obAQoU&n",[global])),
+?line <<"„XAZSd">> = iolist_to_binary(re:replace("„XAZXB","(?<=Z)X.","Sd",[])),
+?line <<"„XAZSd">> = iolist_to_binary(re:replace("„XAZXB","(?<=Z)X.","Sd",[global])),
?line <<"A">> = iolist_to_binary(re:replace("ab cd defg","ab cd (?x) de fg","\\1A\\1",[])),
?line <<"A">> = iolist_to_binary(re:replace("ab cd defg","ab cd (?x) de fg","\\1A\\1",[global])),
?line <<"fab cddefgLdtKCtPab cddefgxvVUHDah">> = iolist_to_binary(re:replace("ab cddefg","ab cd(?x) de fg","f&LdtKC\\1\\1tP&xvVUHDah",[])),
diff --git a/lib/stdlib/test/re_testoutput1_split_test.erl b/lib/stdlib/test/re_testoutput1_split_test.erl
index e86a04b008..4fc85b95c0 100644
--- a/lib/stdlib/test/re_testoutput1_split_test.erl
+++ b/lib/stdlib/test/re_testoutput1_split_test.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -524,14 +525,14 @@ run() ->
?line <<"ething">> = iolist_to_binary(join(re:split("ething","^[^]cde]",[{parts,
2}]))),
?line <<"ething">> = iolist_to_binary(join(re:split("ething","^[^]cde]",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("�","^\\�",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("�","^\\�",[{parts,
+?line <<"">> = iolist_to_binary(join(re:split("","^\\",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("","^\\",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("�","^\\�",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("�","^�",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("�","^�",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("","^\\",[]))),
+?line <<"">> = iolist_to_binary(join(re:split("ÿ","^ÿ",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("ÿ","^ÿ",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("�","^�",[]))),
+?line <<":">> = iolist_to_binary(join(re:split("ÿ","^ÿ",[]))),
?line <<"">> = iolist_to_binary(join(re:split("0","^[0-9]+$",[trim]))),
?line <<":">> = iolist_to_binary(join(re:split("0","^[0-9]+$",[{parts,
2}]))),
@@ -22879,14 +22880,14 @@ def","abc$",[]))),
?line <<":abc:">> = iolist_to_binary(join(re:split("abcS","(abc)\\123",[{parts,
2}]))),
?line <<":abc:">> = iolist_to_binary(join(re:split("abcS","(abc)\\123",[]))),
-?line <<":abc">> = iolist_to_binary(join(re:split("abc�","(abc)\\223",[trim]))),
-?line <<":abc:">> = iolist_to_binary(join(re:split("abc�","(abc)\\223",[{parts,
+?line <<":abc">> = iolist_to_binary(join(re:split("abc“","(abc)\\223",[trim]))),
+?line <<":abc:">> = iolist_to_binary(join(re:split("abc“","(abc)\\223",[{parts,
2}]))),
-?line <<":abc:">> = iolist_to_binary(join(re:split("abc�","(abc)\\223",[]))),
-?line <<":abc">> = iolist_to_binary(join(re:split("abc�","(abc)\\323",[trim]))),
-?line <<":abc:">> = iolist_to_binary(join(re:split("abc�","(abc)\\323",[{parts,
+?line <<":abc:">> = iolist_to_binary(join(re:split("abc“","(abc)\\223",[]))),
+?line <<":abc">> = iolist_to_binary(join(re:split("abcÓ","(abc)\\323",[trim]))),
+?line <<":abc:">> = iolist_to_binary(join(re:split("abcÓ","(abc)\\323",[{parts,
2}]))),
-?line <<":abc:">> = iolist_to_binary(join(re:split("abc�","(abc)\\323",[]))),
+?line <<":abc:">> = iolist_to_binary(join(re:split("abcÓ","(abc)\\323",[]))),
?line <<":abc">> = iolist_to_binary(join(re:split("abc@","(abc)\\100",[trim]))),
?line <<":abc:">> = iolist_to_binary(join(re:split("abc@","(abc)\\100",[{parts,
2}]))),
@@ -28929,42 +28930,42 @@ xb","(?!^)x",[multiline]))),
?line <<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">> = iolist_to_binary(join(re:split("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","(a+)*b",[{parts,
2}]))),
?line <<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">> = iolist_to_binary(join(re:split("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","(a+)*b",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("REGular","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("REGular","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[{parts,
+?line <<"">> = iolist_to_binary(join(re:split("REGular","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("REGular","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("REGular","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("regulaer","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("regulaer","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("REGular","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[]))),
+?line <<"">> = iolist_to_binary(join(re:split("regulaer","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("regulaer","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("regulaer","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("Regex","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("Regex","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("regulaer","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[]))),
+?line <<"">> = iolist_to_binary(join(re:split("Regex","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("Regex","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("Regex","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("regul�r","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("regul�r","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("Regex","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[]))),
+?line <<"">> = iolist_to_binary(join(re:split("regulär","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("regulär","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("regul�r","(?i)reg(?:ul(?:[a�]|ae)r|ex)",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("regulär","(?i)reg(?:ul(?:[aä]|ae)r|ex)",[]))),
+?line <<"">> = iolist_to_binary(join(re:split("Åæåäà","Åæåä[à-ÿÀ-ß]+",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("Åæåäà","Åæåä[à-ÿÀ-ß]+",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("Åæåäà","Åæåä[à-ÿÀ-ß]+",[]))),
+?line <<"">> = iolist_to_binary(join(re:split("Åæåäÿ","Åæåä[à-ÿÀ-ß]+",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("Åæåäÿ","Åæåä[à-ÿÀ-ß]+",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("Åæåäÿ","Åæåä[à-ÿÀ-ß]+",[]))),
+?line <<"">> = iolist_to_binary(join(re:split("ÅæåäÀ","Åæåä[à-ÿÀ-ß]+",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("ÅæåäÀ","Åæåä[à-ÿÀ-ß]+",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[]))),
-?line <<"">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[trim]))),
-?line <<":">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("ÅæåäÀ","Åæåä[à-ÿÀ-ß]+",[]))),
+?line <<"">> = iolist_to_binary(join(re:split("Åæåäß","Åæåä[à-ÿÀ-ß]+",[trim]))),
+?line <<":">> = iolist_to_binary(join(re:split("Åæåäß","Åæåä[à-ÿÀ-ß]+",[{parts,
2}]))),
-?line <<":">> = iolist_to_binary(join(re:split("�����","����[�-��-�]+",[]))),
-?line <<"�XAZ">> = iolist_to_binary(join(re:split("�XAZXB","(?<=Z)X.",[trim]))),
-?line <<"�XAZ:">> = iolist_to_binary(join(re:split("�XAZXB","(?<=Z)X.",[{parts,
+?line <<":">> = iolist_to_binary(join(re:split("Åæåäß","Åæåä[à-ÿÀ-ß]+",[]))),
+?line <<"„XAZ">> = iolist_to_binary(join(re:split("„XAZXB","(?<=Z)X.",[trim]))),
+?line <<"„XAZ:">> = iolist_to_binary(join(re:split("„XAZXB","(?<=Z)X.",[{parts,
2}]))),
-?line <<"�XAZ:">> = iolist_to_binary(join(re:split("�XAZXB","(?<=Z)X.",[]))),
+?line <<"„XAZ:">> = iolist_to_binary(join(re:split("„XAZXB","(?<=Z)X.",[]))),
?line <<"">> = iolist_to_binary(join(re:split("ab cd defg","ab cd (?x) de fg",[trim]))),
?line <<":">> = iolist_to_binary(join(re:split("ab cd defg","ab cd (?x) de fg",[{parts,
2}]))),
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index d49416c150..a32f846bd2 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -29,7 +29,7 @@
progex_bit_syntax/1, progex_records/1,
progex_lc/1, progex_funs/1,
otp_5990/1, otp_6166/1, otp_6554/1, otp_6785/1,
- otp_7184/1, otp_7232/1, otp_8393/1]).
+ otp_7184/1, otp_7232/1, otp_8393/1, otp_10302/1]).
-export([ start_restricted_from_shell/1,
start_restricted_on_command_line/1,restricted_local/1]).
@@ -93,7 +93,7 @@ groups() ->
progex_funs]},
{tickets, [],
[otp_5990, otp_6166, otp_6554, otp_6785, otp_7184,
- otp_7232, otp_8393]}].
+ otp_7232, otp_8393, otp_10302]}].
init_per_suite(Config) ->
Config.
@@ -108,7 +108,7 @@ end_per_group(_GroupName, Config) ->
Config.
--record(state, {bin, reply, leader}).
+-record(state, {bin, reply, leader, unic = latin1}).
start_restricted_from_shell(doc) ->
@@ -374,15 +374,18 @@ records(Config) when is_list(Config) ->
MS = ?MODULE_STRING,
RR1 = "rr(" ++ MS ++ "). #state{}.",
?line "[state]\n"
- "#state{bin = undefined,reply = undefined,leader = undefined}.\n" =
+ "#state{bin = undefined,reply = undefined,leader = undefined,\n"
+ " unic = latin1}.\n" =
t(RR1),
RR2 = "rr(" ++ MS ++ ",[state]). #state{}.",
?line "[state]\n"
- "#state{bin = undefined,reply = undefined,leader = undefined}.\n" =
+ "#state{bin = undefined,reply = undefined,leader = undefined,\n"
+ " unic = latin1}.\n" =
t(RR2),
RR3 = "rr(" ++ MS ++ ",'_'). #state{}.",
?line "[state]\n"
- "#state{bin = undefined,reply = undefined,leader = undefined}.\n" =
+ "#state{bin = undefined,reply = undefined,leader = undefined,\n"
+ " unic = latin1}.\n" =
t(RR3),
RR4 = "rr(" ++ MS ++ ", '_', {d,test1}).",
?line [[state]] = scan(RR4),
@@ -2748,6 +2751,143 @@ prompt_err(B) ->
S = string:strip(S2, both, $"),
string:strip(S, right, $.).
+otp_10302(doc) ->
+ "OTP-10302. Unicode.";
+otp_10302(suite) -> [];
+otp_10302(Config) when is_list(Config) ->
+ Test1 =
+ <<"begin
+ io:setopts([{encoding,utf8}]),
+ [1024] = \"\\x{400}\",
+ rd(rec, {a = \"\\x{400}\"}),
+ ok = rl(rec)
+ end.">>,
+ "-record(rec,{a = \"\x{400}\"}).\nok.\n" = t(Test1),
+
+ Test3 =
+ <<"io:setopts([{encoding,utf8}]).
+ rd(rec, {a = \"\\x{400}\"}).
+ ok = rp(#rec{}).">>,
+ "ok.\nrec\n#rec{a = \"\x{400}\"}.\nok.\n" = t(Test3),
+
+ Test4 =
+ <<"io:setopts([{encoding,utf8}]).
+ A = [1024] = \"\\x{400}\".
+ b().
+ h().">>,
+
+ "ok.\n\"\x{400}\"\nA = \"\x{400}\".\nok.\n"
+ "1: io:setopts([{encoding,utf8}])\n-> ok.\n"
+ "2: A = [1024] = \"\x{400}\"\n-> \"\x{400}\"\n"
+ "3: b()\n-> ok.\nok.\n" = t(Test4),
+
+ Test5 =
+ <<"begin
+ io:setopts([{encoding,utf8}]),
+ results(0),
+ A = [1024] = \"\\x{400}\",
+ b(),
+ h()
+ end.">>,
+ "A = \"\x{400}\".\nok.\n" = t(Test5),
+
+ %% One $" is "lost":
+ true =
+ "\x{400}\": command not found" =:=
+ prompt_err({<<"io:setopts([{encoding,utf8}]). v(\"\x{400}\")."/utf8>>,
+ unicode}),
+
+ "ok.\ndefault\n* Bad prompt function: \"\x{400}\".\n" =
+ t({<<"io:setopts([{encoding,utf8}]). "
+ "shell:prompt_func(\"\x{400}\")."/utf8>>,
+ unicode}),
+ _ = shell:prompt_func(default),
+
+ %% Test lib:format_exception() (cf. OTP-6554)
+ Test6 =
+ <<"begin
+ A = <<\"\\xaa\">>,
+ S = lists:flatten(io_lib:format(\"~p/~p.\", [A, A])),
+ {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Es} = erl_parse:parse_exprs(Ts),
+ B = erl_eval:new_bindings(),
+ erl_eval:exprs(Es, B)
+ end.">>,
+
+ "** exception error: an error occurred when evaluating"
+ " an arithmetic expression\n in operator '/'/2\n"
+ " called as <<\"\xaa\">> / <<\"\xaa\">>.\n" = t(Test6),
+ Test7 =
+ <<"io:setopts([{encoding,utf8}]).
+ A = <<\"\\xaa\">>,
+ S = lists:flatten(io_lib:format(\"~p/~p.\", [A, A])),
+ {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Es} = erl_parse:parse_exprs(Ts),
+ B = erl_eval:new_bindings(),
+ erl_eval:exprs(Es, B).">>,
+
+ "ok.\n** exception error: an error occurred when evaluating"
+ " an arithmetic expression\n in operator '/'/2\n"
+ " called as <<170>> / <<170>>.\n" = t(Test7),
+ Test8 =
+ <<"begin
+ A = [1089],
+ S = lists:flatten(io_lib:format(\"~tp/~tp.\", [A, A])),
+ {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Es} = erl_parse:parse_exprs(Ts),
+ B = erl_eval:new_bindings(),
+ erl_eval:exprs(Es, B)
+ end.">>,
+ "** exception error: an error occurred when evaluating"
+ " an arithmetic expression\n in operator '/'/2\n"
+ " called as [1089] / [1089].\n" = t(Test8),
+ Test9 =
+ <<"io:setopts([{encoding,utf8}]).
+ A = [1089],
+ S = lists:flatten(io_lib:format(\"~tp/~tp.\", [A, A])),
+ {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Es} = erl_parse:parse_exprs(Ts),
+ B = erl_eval:new_bindings(),
+ erl_eval:exprs(Es, B).">>,
+
+ "ok.\n** exception error: an error occurred when evaluating"
+ " an arithmetic expression\n in operator '/'/2\n"
+ " called as \"\x{441}\" / \"\x{441}\".\n" = t(Test9),
+ Test10 =
+ <<"A = {\"1\\xaa\",
+ $\\xaa,
+ << <<\"hi\">>/binary >>,
+ <<\"1\xaa\">>},
+ fun(a) -> true end(A).">>,
+ "** exception error: no function clause matching \n"
+ " erl_eval:'-inside-an-interpreted-fun-'"
+ "({\"1\xc2\xaa\",170,<<\"hi\">>,\n "
+ " <<\"1\xc2\xaa\">>}) .\n" = t(Test10),
+ Test11 =
+ <<"io:setopts([{encoding,utf8}]).
+ A = {\"1\\xaa\",
+ $\\xaa,
+ << <<\"hi\">>/binary >>,
+ <<\"1\xaa\">>},
+ fun(a) -> true end(A).">>,
+
+ "ok.\n** exception error: no function clause matching \n"
+ " erl_eval:'-inside-an-interpreted-fun-'"
+ "({\"1\xaa\",170,<<\"hi\">>,\n "
+ " <<\"1\xaa\"/utf8>>}) .\n" = t(Test11),
+ Test12 = <<"fun(a, b) -> false end(65, [1089]).">>,
+ "** exception error: no function clause matching \n"
+ " erl_eval:'-inside-an-interpreted-fun-'(65,[1089])"
+ " .\n" = t(Test12),
+ Test13 =
+ <<"io:setopts([{encoding,utf8}]).
+ fun(a, b) -> false end(65, [1089]).">>,
+ "ok.\n** exception error: no function clause matching \n"
+ " erl_eval:'-inside-an-interpreted-fun-'(65,\"\x{441}\")"
+ " .\n" = t(Test13),
+
+ ok.
+
scan(B) ->
F = fun(Ts) ->
case erl_parse:parse_term(Ts) of
@@ -2761,7 +2901,7 @@ scan(B) ->
scan(t(B), F).
scan(S0, F) ->
- case erl_scan:tokens([], S0, 1) of
+ case erl_scan:tokens([], S0, 1, [unicode]) of
{done,{ok,Ts,_},S} ->
[F(Ts) | scan(S, F)];
_Else ->
@@ -2769,29 +2909,36 @@ scan(S0, F) ->
end.
t({Node,Bin}) when is_atom(Node),is_binary(Bin) ->
- t0(Bin, fun() -> start_new_shell(Node) end);
+ t0({Bin,latin1}, fun() -> start_new_shell(Node) end);
t(Bin) when is_binary(Bin) ->
- t0(Bin, fun() -> start_new_shell() end);
+ t0({Bin,latin1}, fun() -> start_new_shell() end);
+t({Bin,Enc}) when is_binary(Bin), is_atom(Enc) ->
+ t0({Bin,Enc}, fun() -> start_new_shell() end);
t(L) ->
t(list_to_binary(L)).
-t0(Bin, F) ->
+t0({Bin,Enc}, F) ->
%% Spawn a process so that io_request messages do not interfer.
P = self(),
- C = spawn(fun() -> t1(P, Bin, F) end),
+ C = spawn(fun() -> t1(P, {Bin, Enc}, F) end),
receive {C, R} -> R end.
-t1(Parent, Bin, F) ->
- %% io:format("*** Testing ~s~n", [binary_to_list(Bin)]),
- S = #state{bin = Bin, reply = [], leader = group_leader()},
+t1(Parent, {Bin,Enc}, F) ->
+ io:format("*** Testing ~s~n", [binary_to_list(Bin)]),
+ S = #state{bin = Bin, unic = Enc, reply = [], leader = group_leader()},
group_leader(self(), self()),
_Shell = F(),
try
server_loop(S)
catch exit:R -> Parent ! {self(), R};
- throw:{?MODULE,LoopReply} ->
+ throw:{?MODULE,LoopReply,latin1} ->
L0 = binary_to_list(list_to_binary(LoopReply)),
[$\n | L1] = lists:dropwhile(fun(X) -> X =/= $\n end, L0),
+ Parent ! {self(), dotify(L1)};
+ throw:{?MODULE,LoopReply,_Uni} ->
+ Tmp = unicode:characters_to_binary(LoopReply),
+ L0 = unicode:characters_to_list(Tmp),
+ [$\n | L1] = lists:dropwhile(fun(X) -> X =/= $\n end, L0),
Parent ! {self(), dotify(L1)}
after group_leader(S#state.leader, self())
end.
@@ -2835,7 +2982,7 @@ do_io_request(Req, From, S, ReplyAs) ->
case io_requests([Req], [], S) of
{_Status,{eof,_},S1} ->
io_reply(From, ReplyAs, {error,terminated}),
- throw({?MODULE,S1#state.reply});
+ throw({?MODULE,S1#state.reply,S1#state.unic});
{_Status,Reply,S1} ->
io_reply(From, ReplyAs, Reply),
S1
@@ -2858,13 +3005,34 @@ io_requests([], [Rs|Cont], S) ->
io_requests([], [], S) ->
{ok,ok,S}.
+io_request({setopts, Opts}, S) ->
+ #state{unic = OldEnc, bin = Bin} = S,
+ NewEnc = case proplists:get_value(encoding, Opts) of
+ undefined -> OldEnc;
+ utf8 -> unicode;
+ New -> New
+ end,
+ NewBin = case {OldEnc, NewEnc} of
+ {E, E} -> Bin;
+ {latin1, _} ->
+ unicode:characters_to_binary(Bin, latin1, unicode);
+ {_, latin1} ->
+ unicode:characters_to_binary(Bin, unicode, latin1);
+ {_, _} -> Bin
+ end,
+ {ok, ok, S#state{unic = NewEnc, bin = NewBin}};
+io_request(getopts, S) ->
+ {ok,[{encoding,S#state.unic}],S};
io_request({get_geometry,columns}, S) ->
{ok,80,S};
io_request({get_geometry,rows}, S) ->
{ok,24,S};
io_request({put_chars,Chars}, S) ->
{ok,ok,S#state{reply = [S#state.reply | Chars]}};
-io_request({put_chars,_,Chars}, S) ->
+io_request({put_chars,latin1,Chars}, S) ->
+ {ok,ok,S#state{reply = [S#state.reply | Chars]}};
+io_request({put_chars,unicode,Chars0}, S) ->
+ Chars = unicode:characters_to_list(Chars0),
{ok,ok,S#state{reply = [S#state.reply | Chars]}};
io_request({put_chars,Mod,Func,Args}, S) ->
case catch apply(Mod, Func, Args) of
@@ -2890,9 +3058,12 @@ get_until_loop(M, F, As, S, {more,Cont}, Enc) ->
0 ->
get_until_loop(M, F, As, S,
catch apply(M, F, [Cont,eof|As]), Enc);
+ _ when S#state.unic =:= latin1 ->
+ get_until_loop(M, F, As, S#state{bin = <<>>},
+ catch apply(M, F, [Cont,binary_to_list(Bin)|As]), Enc);
_ ->
get_until_loop(M, F, As, S#state{bin = <<>>},
- catch apply(M, F, [Cont,binary_to_list(Bin)|As]), Enc)
+ catch apply(M, F, [Cont,unicode:characters_to_list(Bin)|As]), Enc)
end;
get_until_loop(_M, _F, _As, S, {done,Res,Buf}, Enc) ->
{ok,Res,S#state{bin = buf2bin(Buf, Enc)}};
@@ -2903,6 +3074,8 @@ buf2bin(eof,_) ->
<<>>;
buf2bin(Buf,latin1) ->
list_to_binary(Buf);
+buf2bin(Buf,utf8) ->
+ unicode:characters_to_binary(Buf,unicode,unicode);
buf2bin(Buf,unicode) ->
unicode:characters_to_binary(Buf,unicode,unicode).
diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl
index 6969c095a0..96e653985f 100644
--- a/lib/stdlib/test/string_SUITE.erl
+++ b/lib/stdlib/test/string_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -473,8 +474,8 @@ to_upper_to_lower(suite) ->
to_upper_to_lower(doc) ->
[];
to_upper_to_lower(Config) when is_list(Config) ->
- ?line "1234ABCDEF���=" = string:to_upper("1234abcdef���="),
- ?line "����������abc()" = string:to_lower("����������abc()"),
+ ?line "1234ABCDEFÅÄÖ=" = string:to_upper("1234abcdefåäö="),
+ ?line "éèíúùòóåäöabc()" = string:to_lower("ÉÈÍÚÙÒÓÅÄÖabc()"),
?line All = lists:seq(0, 255),
?line UC = string:to_upper(All),
diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl
index b3ced34c14..70395848a1 100644
--- a/lib/syntax_tools/src/epp_dodger.erl
+++ b/lib/syntax_tools/src/epp_dodger.erl
@@ -186,6 +186,7 @@ quick_parse_file(File, Options) ->
parse_file(File, Parser, Options) ->
case file:open(File, [read]) of
{ok, Dev} ->
+ _ = epp:set_encoding(Dev),
try Parser(Dev, 1, Options)
after ok = file:close(Dev)
end;
@@ -400,7 +401,7 @@ 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
+ case io:scan_erl_form(Dev, "", L0, [unicode]) of
{ok, Ts, L1} ->
case catch {ok, Parser(Ts, Opt)} of
{'EXIT', Term} ->
@@ -419,6 +420,7 @@ parse_form(Dev, L0, Parser, Options) ->
{ok, F, L1}
end;
{error, _IoErr, _L1} = Err -> Err;
+ {error, _Reason} -> {eof, L0}; % This is probably encoding problem
{eof, _L1} = Eof -> Eof
end.
diff --git a/lib/syntax_tools/src/erl_comment_scan.erl b/lib/syntax_tools/src/erl_comment_scan.erl
index b833e1c069..a70e7ba413 100644
--- a/lib/syntax_tools/src/erl_comment_scan.erl
+++ b/lib/syntax_tools/src/erl_comment_scan.erl
@@ -72,7 +72,17 @@ file(Name) ->
{ok, V} ->
case V of
{ok, B} ->
- string(binary_to_list(B));
+ Enc = case epp:read_encoding(Name) of
+ none -> epp:default_encoding();
+ Enc0 -> Enc0
+ end,
+ case catch unicode:characters_to_list(B, Enc) of
+ String when is_list(String) ->
+ string(String);
+ R ->
+ error_read_file(Name1),
+ exit(R)
+ end;
{error, E} ->
error_read_file(Name1),
exit({read, E})
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index f4bbf975c3..1a55a5e71c 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -60,7 +60,9 @@
hook = ?NOHOOK :: hook(),
paper = ?PAPER :: integer(),
ribbon = ?RIBBON :: integer(),
- user = ?NOUSER :: term()}).
+ user = ?NOUSER :: term(),
+ encoding = epp:default_encoding() :: epp:source_encoding()}).
+
-type context() :: #ctxt{}.
%% =====================================================================
@@ -231,6 +233,8 @@ format(Node) ->
%% <dt>{user, term()}</dt>
%% <dd>User-specific data for use in hook functions. The default
%% value is `undefined'.</dd>
+%% <dt>{encoding, epp:source_encoding()}</dt>
+%% <dd>Specifies the encoding of the generated file.</dd>
%% </dl>
%%
%% A hook function (cf. the {@link hook()} type) is passed the current
@@ -342,7 +346,9 @@ layout(Node, Options) ->
#ctxt{hook = proplists:get_value(hook, Options, ?NOHOOK),
paper = proplists:get_value(paper, Options, ?PAPER),
ribbon = proplists:get_value(ribbon, Options, ?RIBBON),
- user = proplists:get_value(user, Options)}).
+ user = proplists:get_value(user, Options),
+ encoding = proplists:get_value(encoding, Options,
+ epp:default_encoding())}).
lay(Node, Ctxt) ->
case erl_syntax:get_ann(Node) of
@@ -445,10 +451,10 @@ lay_2(Node, Ctxt) ->
text(tidy_float(erl_syntax:float_literal(Node)));
char ->
- text(erl_syntax:char_literal(Node));
+ text(erl_syntax:char_literal(Node, Ctxt#ctxt.encoding));
string ->
- lay_string(erl_syntax:string_literal(Node), Ctxt);
+ lay_string(erl_syntax:string_literal(Node, Ctxt#ctxt.encoding), Ctxt);
nil ->
text("[]");
@@ -639,10 +645,6 @@ lay_2(Node, Ctxt) ->
set_prec(Ctxt, PrecR)),
beside(D1, beside(text(":"), D2));
- qualified_name ->
- Ss = erl_syntax:qualified_name_segments(Node),
- lay_qualified_name(Ss, Ctxt);
-
%%
%% The rest is in alphabetical order
%%
@@ -966,26 +968,6 @@ maybe_parentheses(D, Prec, Ctxt) ->
D
end.
-lay_qualified_name([S | Ss1] = Ss, Ctxt) ->
- case erl_syntax:type(S) of
- atom ->
- case erl_syntax:atom_value(S) of
- '' ->
- beside(text("."),
- lay_qualified_name_1(Ss1, Ctxt));
- _ ->
- lay_qualified_name_1(Ss, Ctxt)
- end;
- _ ->
- lay_qualified_name_1(Ss, Ctxt)
- end.
-
-lay_qualified_name_1([S], Ctxt) ->
- lay(S, Ctxt);
-lay_qualified_name_1([S | Ss], Ctxt) ->
- beside(lay(S, Ctxt), beside(text("."),
- lay_qualified_name_1(Ss, Ctxt))).
-
lay_string(S, Ctxt) ->
%% S includes leading/trailing double-quote characters. The segment
%% width is 2/3 of the ribbon width - this seems to work well.
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 151f04b03b..f7420030c3 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -161,6 +161,7 @@
is_char/2,
char_value/1,
char_literal/1,
+ char_literal/2,
clause/2,
clause/3,
clause_body/1,
@@ -234,8 +235,6 @@
prefix_expr/2,
prefix_expr_argument/1,
prefix_expr_operator/1,
- qualified_name/1,
- qualified_name_segments/1,
query_expr/1,
query_expr_body/1,
receive_expr/1,
@@ -271,6 +270,7 @@
is_string/2,
string_value/1,
string_literal/1,
+ string_literal/2,
text/1,
text_string/1,
try_expr/2,
@@ -449,7 +449,6 @@
%% <td>parentheses</td>
%% <td>prefix_expr</td>
%% </tr><tr>
-%% <td>qualified_name</td>
%% <td>query_expr</td>
%% <td>receive_expr</td>
%% <td>record_access</td>
@@ -514,7 +513,6 @@
%% @see operator/1
%% @see parentheses/1
%% @see prefix_expr/2
-%% @see qualified_name/1
%% @see query_expr/1
%% @see receive_expr/3
%% @see record_access/3
@@ -584,11 +582,7 @@ type(Node) ->
{record, _, _, _, _} -> record_expr;
{record, _, _, _} -> record_expr;
{record_field, _, _, _, _} -> record_access;
- {record_field, _, _, _} ->
- case is_qualified_name(Node) of
- true -> qualified_name;
- false -> record_access
- end;
+ {record_field, _, _, _} -> record_access;
{record_index, _, _, _} -> record_index_expr;
{remote, _, _, _} -> module_qualifier;
{rule, _, _, _, _} -> rule;
@@ -1628,6 +1622,7 @@ float_literal(Node) ->
%%
%% @see char_value/1
%% @see char_literal/1
+%% @see char_literal/2
%% @see is_char/2
%% type(Node) = char
@@ -1687,13 +1682,34 @@ char_value(Node) ->
%% =====================================================================
%% @doc Returns the literal string represented by a `char'
%% node. This includes the leading "`$'" character.
+%% Characters beyond 255 will be escaped.
%%
%% @see char/1
-spec char_literal(syntaxTree()) -> nonempty_string().
char_literal(Node) ->
- io_lib:write_char(char_value(Node)).
+ char_literal(Node, latin1).
+
+
+%% =====================================================================
+%% @doc Returns the literal string represented by a `char'
+%% node. This includes the leading "`$'" character.
+%% Depending on the encoding a character beyond 255 will be escaped
+%% ('latin1') or copied as is ('utf8').
+%%
+%% @see char/1
+
+-type encoding() :: 'utf8' | 'unicode' | 'latin1'.
+
+-spec char_literal(syntaxTree(), encoding()) -> nonempty_string().
+
+char_literal(Node, unicode) ->
+ io_lib:write_unicode_char(char_value(Node));
+char_literal(Node, utf8) ->
+ io_lib:write_unicode_char(char_value(Node));
+char_literal(Node, latin1) ->
+ io_lib:write_unicode_char_as_latin1(char_value(Node)).
%% =====================================================================
@@ -1708,6 +1724,7 @@ char_literal(Node) ->
%%
%% @see string_value/1
%% @see string_literal/1
+%% @see string_literal/2
%% @see is_string/2
%% @see char/1
@@ -1768,13 +1785,32 @@ string_value(Node) ->
%% =====================================================================
%% @doc Returns the literal string represented by a `string'
%% node. This includes surrounding double-quote characters.
+%% Characters beyond 255 will be escaped.
%%
%% @see string/1
-spec string_literal(syntaxTree()) -> nonempty_string().
string_literal(Node) ->
- io_lib:write_string(string_value(Node)).
+ string_literal(Node, latin1).
+
+
+%% =====================================================================
+%% @doc Returns the literal string represented by a `string'
+%% node. This includes surrounding double-quote characters.
+%% Depending on the encoding characters beyond 255 will be escaped
+%% ('latin1') or copied as is ('utf8').
+%%
+%% @see string/1
+
+-spec string_literal(syntaxTree(), encoding()) -> nonempty_string().
+
+string_literal(Node, utf8) ->
+ io_lib:write_unicode_string(string_value(Node));
+string_literal(Node, unicode) ->
+ io_lib:write_unicode_string(string_value(Node));
+string_literal(Node, latin1) ->
+ io_lib:write_unicode_string_as_latin1(string_value(Node)).
%% =====================================================================
@@ -3003,9 +3039,6 @@ revert_module_name(A) ->
case type(A) of
atom ->
{ok, concrete(A)};
- qualified_name ->
- Ss = qualified_name_segments(A),
- {ok, [concrete(S) || S <- Ss]};
_ ->
error
end.
@@ -3051,11 +3084,7 @@ attribute_arguments(Node) ->
M0 ->
{M0, none}
end,
- M2 = if is_list(M1) ->
- qualified_name([atom(A) || A <- M1]);
- true ->
- atom(M1)
- end,
+ M2 = atom(M1),
M = set_pos(M2, Pos),
if Vs == none -> [M];
true -> [M, set_pos(list(Vs), Pos)]
@@ -3065,20 +3094,11 @@ attribute_arguments(Node) ->
list(unfold_function_names(Data, Pos)),
Pos)];
import ->
- case Data of
- {Module, Imports} ->
- [if is_list(Module) ->
- qualified_name([atom(A)
- || A <- Module]);
- true ->
- set_pos(atom(Module), Pos)
- end,
- set_pos(
- list(unfold_function_names(Imports, Pos)),
- Pos)];
- _ ->
- [qualified_name([atom(A) || A <- Data])]
- end;
+ {Module, Imports} = Data,
+ [set_pos(atom(Module), Pos),
+ set_pos(
+ list(unfold_function_names(Imports, Pos)),
+ Pos)];
file ->
{File, Line} = Data,
[set_pos(string(File), Pos),
@@ -3210,53 +3230,6 @@ module_qualifier_body(Node) ->
%% =====================================================================
-%% @doc Creates an abstract qualified name. The result represents
-%% "<code><em>S1</em>.<em>S2</em>. ... .<em>Sn</em></code>", if
-%% `Segments' is `[S1, S2, ..., Sn]'.
-%%
-%% @see qualified_name_segments/1
-
-%% type(Node) = qualified_name
-%% data(Node) = [syntaxTree()]
-%%
-%% `erl_parse' representation:
-%%
-%% {record_field, Pos, Node, Node}
-%%
-%% Node = {atom, Pos, Value} | {record_field, Pos, Node, Node}
-%%
-%% Note that if not all leaf subnodes are (abstract) atoms, then Node
-%% represents a Mnemosyne query record field access ('record_access');
-%% see type/1 for details.
-
--spec qualified_name([syntaxTree()]) -> syntaxTree().
-
-qualified_name(Segments) ->
- tree(qualified_name, Segments).
-
-revert_qualified_name(Node) ->
- Pos = get_pos(Node),
- fold_qualified_name(qualified_name_segments(Node), Pos).
-
-
-%% =====================================================================
-%% @doc Returns the list of name segments of a
-%% `qualified_name' node.
-%%
-%% @see qualified_name/1
-
--spec qualified_name_segments(syntaxTree()) -> [syntaxTree()].
-
-qualified_name_segments(Node) ->
- case unwrap(Node) of
- {record_field, _, _, _} = Node1 ->
- unfold_qualified_name(Node1);
- Node1 ->
- data(Node1)
- end.
-
-
-%% =====================================================================
%% @doc Creates an abstract function definition. If `Clauses'
%% is `[C1, ..., Cn]', the result represents
%% "<code><em>Name</em> <em>C1</em>; ...; <em>Name</em>
@@ -6068,8 +6041,6 @@ revert_root(Node) ->
revert_parentheses(Node);
prefix_expr ->
revert_prefix_expr(Node);
- qualified_name ->
- revert_qualified_name(Node);
query_expr ->
revert_query_expr(Node);
receive_expr ->
@@ -6312,8 +6283,6 @@ subtrees(T) ->
prefix_expr ->
[[prefix_expr_operator(T)],
[prefix_expr_argument(T)]];
- qualified_name ->
- [qualified_name_segments(T)];
query_expr ->
[[query_expr_body(T)]];
receive_expr ->
@@ -6444,7 +6413,6 @@ make_tree(match_expr, [[P], [E]]) -> match_expr(P, E);
make_tree(module_qualifier, [[M], [N]]) -> module_qualifier(M, N);
make_tree(parentheses, [[E]]) -> parentheses(E);
make_tree(prefix_expr, [[F], [A]]) -> prefix_expr(F, A);
-make_tree(qualified_name, [S]) -> qualified_name(S);
make_tree(query_expr, [[B]]) -> query_expr(B);
make_tree(receive_expr, [C]) -> receive_expr(C);
make_tree(receive_expr, [C, [E], A]) -> receive_expr(C, E, A);
@@ -6788,32 +6756,6 @@ fold_variable_names(Vs) ->
unfold_variable_names(Vs, Pos) ->
[set_pos(variable(V), Pos) || V <- Vs].
-%% Support functions for qualified names ("foo.bar.baz",
-%% "erl.lang.lists", etc.). The representation overlaps with the weird
-%% "Mnesia query record access" operators. The '.' operator is left
-%% associative, so folding should nest on the left.
-
-is_qualified_name({record_field, _, L, R}) ->
- is_qualified_name(L) andalso is_qualified_name(R);
-is_qualified_name({atom, _, _}) -> true;
-is_qualified_name(_) -> false.
-
-unfold_qualified_name(Node) ->
- lists:reverse(unfold_qualified_name(Node, [])).
-
-unfold_qualified_name({record_field, _, L, R}, Ss) ->
- unfold_qualified_name(R, unfold_qualified_name(L, Ss));
-unfold_qualified_name(S, Ss) -> [S | Ss].
-
-fold_qualified_name([S | Ss], Pos) ->
- fold_qualified_name(Ss, Pos, {atom, Pos, atom_value(S)}).
-
-fold_qualified_name([S | Ss], Pos, Ack) ->
- fold_qualified_name(Ss, Pos, {record_field, Pos, Ack,
- {atom, Pos, atom_value(S)}});
-fold_qualified_name([], _Pos, Ack) ->
- Ack.
-
%% Support functions for transforming lists of record field definitions.
%%
%% There is no unique representation for field definitions in the
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index 36cd35f15d..2c94ac776d 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -2223,11 +2223,6 @@ module_name_to_atom(M) ->
case erl_syntax:type(M) of
atom ->
erl_syntax:atom_value(M);
- qualified_name ->
- list_to_atom(packages:concat(
- [erl_syntax:atom_value(A)
- || A <- erl_syntax:qualified_name_segments(M)])
- );
_ ->
throw(syntax_error)
end.
diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl
index 59cf6c0a92..e9a88caff3 100644
--- a/lib/syntax_tools/src/erl_tidy.erl
+++ b/lib/syntax_tools/src/erl_tidy.erl
@@ -375,6 +375,8 @@ write_module(Tree, Name, Opts) ->
end,
filename(filename:join(Dir, Name1))
end,
+ Encoding = [{encoding,Enc} || Enc <- [epp:read_encoding(Name)],
+ Enc =/= none],
case proplists:get_bool(backups, Opts) of
true ->
backup_file(File, Opts);
@@ -382,9 +384,9 @@ write_module(Tree, Name, Opts) ->
ok
end,
Printer = proplists:get_value(printer, Opts),
- FD = open_output_file(File),
+ FD = open_output_file(File, Encoding),
verbose("writing to file `~s'.", [File], Opts),
- V = (catch {ok, output(FD, Printer, Tree, Opts)}),
+ V = (catch {ok, output(FD, Printer, Tree, Opts++Encoding)}),
ok = file:close(FD),
case V of
{ok, _} ->
@@ -432,8 +434,9 @@ file_type(Name, Links) ->
throw(R)
end.
-open_output_file(FName) ->
- case catch file:open(FName, [write]) of
+open_output_file(FName, Options) ->
+io:format("Options ~p~n", [Options]),
+ case catch file:open(FName, [write]++Options) of
{ok, FD} ->
FD;
{error, R} ->
diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl
index 37e561cbbe..8abc3f41cb 100644
--- a/lib/syntax_tools/src/igor.erl
+++ b/lib/syntax_tools/src/igor.erl
@@ -341,10 +341,12 @@ merge(Name, Files) ->
merge(Name, Files, Opts) ->
Opts1 = Opts ++ ?DEFAULT_MERGE_OPTS,
- {Tree, Stubs} = merge_files(Name, Files, Opts1),
+ {Sources, Enc} = merge_files1(Files, Opts1),
+ {Tree, Stubs} = merge_sources(Name, Sources, Opts1),
Dir = proplists:get_value(dir, Opts1, ""),
Filename = proplists:get_value(outfile, Opts1, Name),
- File = write_module(Tree, Filename, Dir, Opts1),
+ Encoding = [{encoding, Enc} || Enc =/= none],
+ File = write_module(Tree, Filename, Dir, Encoding ++ Opts1),
[File | maybe_create_stubs(Stubs, Opts1)].
@@ -459,16 +461,21 @@ merge_files(Name, Files, Options) ->
-spec merge_files(atom(), erl_syntax:forms(), [file:filename()], [option()]) ->
{erl_syntax:syntaxTree(), [stubDescriptor()]}.
-merge_files(_, _Trees, [], _) ->
+merge_files(Name, Trees, Files, Opts) ->
+ {Sources, _Encoding} = merge_files1(Files, Opts),
+ merge_sources(Name, Trees ++ Sources, Opts).
+
+merge_files1([], _) ->
report_error("no files to merge."),
exit(badarg);
-merge_files(Name, Trees, Files, Opts) ->
+merge_files1(Files, Opts) ->
Opts1 = Opts ++ [{includes, ?DEFAULT_INCLUDES},
{macros, ?DEFAULT_MACROS},
{preprocess, false},
comments],
- Sources = [read_module(F, Opts1) || F <- Files],
- merge_sources(Name, Trees ++ Sources, Opts1).
+ SourceEncodings = [read_module(F, Opts1) || F <- Files],
+ {Sources, [Encoding | _]} = lists:unzip(SourceEncodings),
+ {Sources, Encoding}.
%% =====================================================================
@@ -2512,7 +2519,11 @@ rename(Files, Renamings, Opts) ->
lists:flatmap(fun (F) -> rename_file(F, Dict, Opts1) end, Files).
rename_file(File, Dict, Opts) ->
- S = read_module(File, Opts),
+ {S, Enc} = read_module(File, Opts),
+ %% Try to avoid *two* coding: comments:
+ Encoding = [{encoding, Enc} ||
+ Enc =/= none,
+ not proplists:get_bool(comments, Opts)],
M = get_module_info(S),
Name = M#module.name,
Name1 = case dict:find(Name, Dict) of
@@ -2526,10 +2537,10 @@ rename_file(File, Dict, Opts) ->
Opts1 = [no_headers,
{export, [Name]},
{static, [Name]},
- {redirect, dict:to_list(Dict1)}] ++ Opts,
+ {redirect, dict:to_list(Dict1)}] ++ Encoding ++ Opts,
{Tree, Stubs} = merge_sources(Name1, [S], Opts1),
Dir = filename:dirname(filename(File)),
- File1 = write_module(Tree, Name1, Dir, Opts),
+ File1 = write_module(Tree, Name1, Dir, Opts++Encoding),
%% We create the stub file in the same directory as the source file
%% and the target file.
@@ -2648,7 +2659,7 @@ error_text(D, Name) ->
{L, M, E} when is_integer(L), is_atom(M) ->
case catch M:format_error(E) of
S when is_list(S) ->
- io_lib:fwrite("`~w', line ~w: ~s.",
+ io_lib:fwrite("`~w', line ~w: ~ts.",
[Name, L, S]);
_ ->
error_text_1(D, Name)
@@ -2706,7 +2717,17 @@ open_output_file(FName) ->
exit(R)
end.
-%% read_module(Name, Options) -> syntaxTree()
+output_encoding(FD, Opts) ->
+ case proplists:get_value(encoding, Opts) of
+ undefined ->
+ ok = io:setopts(FD, [{encoding, epp:default_encoding()}]);
+ Encoding ->
+ ok = io:setopts(FD, [{encoding, Encoding}]),
+ EncS = epp:encoding_to_string(Encoding),
+ ok = io:fwrite(FD, <<"%% ~s\n">>, [EncS])
+ end.
+
+%% read_module(Name, Options) -> {syntaxTree(), epp:source_encoding()}
%%
%% This also tries to locate the real source file, if "Name" does not
%% point directly to a particular file.
@@ -2729,20 +2750,21 @@ read_module(Name, Options) ->
read_module_1(Name, Options) ->
verbose("reading module `~s'.", [filename(Name)], Options),
- Forms = read_module_2(Name, Options),
+ {Forms, Enc} = read_module_2(Name, Options),
case proplists:get_bool(comments, Options) of
false ->
- Forms;
+ {Forms, Enc};
true ->
Comments = erl_comment_scan:file(Name),
- erl_recomment:recomment_forms(Forms, Comments)
+ {erl_recomment:recomment_forms(Forms, Comments), Enc}
end.
read_module_2(Name, Options) ->
case read_module_3(Name, Options) of
{ok, Forms} ->
check_forms(Forms, Name),
- Forms;
+ Enc = epp:read_encoding(Name),
+ {Forms, Enc};
{error, _} = Error ->
error_read_file(Name),
exit(Error)
@@ -2772,7 +2794,7 @@ check_forms([F | Fs], File) ->
_ ->
"unknown error"
end,
- report_error("in file `~s' at line ~w:\n ~s",
+ report_error("in file `~s' at line ~w:\n ~ts",
[filename(File), erl_syntax:get_pos(F), S]),
exit(error);
_ ->
@@ -2847,6 +2869,7 @@ write_module(Tree, Name, Dir, Opts) ->
end,
Printer = proplists:get_value(printer, Opts),
FD = open_output_file(File),
+ ok = output_encoding(FD, Opts),
verbose("writing to file `~s'.", [File], Opts),
V = (catch {ok, output(FD, Printer, Tree, Opts)}),
ok = file:close(FD),
diff --git a/lib/test_server/doc/src/test_server_ctrl.xml b/lib/test_server/doc/src/test_server_ctrl.xml
index 41bc0bcc75..af96f1fe7e 100644
--- a/lib/test_server/doc/src/test_server_ctrl.xml
+++ b/lib/test_server/doc/src/test_server_ctrl.xml
@@ -427,11 +427,21 @@ Optional, if not given the test server controller node
<p>A <c>CoverFile</c> can have the following entries:</p>
<code type="none">
{exclude, all | ExcludeModuleList}.
-{include, IncludeModuleList}. </code>
+{include, IncludeModuleList}.
+{cross, CrossCoverInfo}.</code>
<p>Note that each line must end with a full
stop. <c>ExcludeModuleList</c> and <c>IncludeModuleList</c>
are lists of atoms, where each atom is a module name.
</p>
+
+ <p><c>CrossCoverInfo</c> is used when collecting cover data
+ over multiple tests. Modules listed here are compiled, but
+ they will not be analysed when the test is finished. See
+ <seealso
+ marker="#cross_cover_analyse-2">cross_cover_analyse/2</seealso>
+ for more information about the cross cover mechanism and the
+ format of <c>CrossCoverInfo</c>.
+ </p>
<p>If both an <c>Application</c> and a <c>CoverFile</c> is
given, all modules in the application are cover compiled,
except for the modules listed in <c>ExcludeModuleList</c>. The
@@ -467,30 +477,71 @@ Optional, if not given the test server controller node
</desc>
</func>
<func>
- <name>cross_cover_analyse(Level) -> ok</name>
- <fsummary>Analyse cover data collected from all tests</fsummary>
+ <name>cross_cover_analyse(Level, Tests) -> ok</name>
+ <fsummary>Analyse cover data collected from multiple tests</fsummary>
<type>
<v>Level = details | overview</v>
+ <v>Tests = [{Tag,LogDir}]</v>
+ <v>Tag = atom()</v>
+ <d>Test identifier.</d>
+ <v>LogDir = string()</v>
+ <d>Log directory for the test identified by <c>Tag</c>. This
+ can either be the <c>run.&lt;timestamp&gt;</c> directory or
+ the parent directory of this (in which case the latest
+ <c>run.&lt;timestamp&gt;</c> directory is chosen.</d>
</type>
<desc>
- <p>Analyse cover data collected from all tests. The modules
- analysed are the ones listed in the cross cover file
- <c>cross.cover</c> in the current directory of the test
- server.</p>
- <p>The modules listed in the <c>cross.cover</c> file are
- modules that are heavily used by other applications than the
- one they belong to. This function should be run after all
- tests are completed, and the result will be stored in a file
- called cross_cover.html in the run.&lt;timestamp&gt;
- directory of the application the modules belong to.
- </p>
- <p>The <c>cross.cover</c> file contains elements like this:</p>
- <pre>
-{App,Modules}. </pre>
- <p>where <c>App</c> can be an application name or the atom
- <c>all</c>. The application (or all applications) will cover
- compile the listed <c>Modules</c>.
- </p>
+ <p>Analyse cover data collected from multiple tests. The modules
+ analysed are the ones listed in <c>cross</c> statements in
+ the cover files. These are modules that are heavily used by
+ other tests than the one where they belong or are explicitly
+ tested. They should then be listed as cross modules in the
+ cover file for the test where they are used but do not
+ belong. Se example below.</p>
+ <p>This function should be run after all tests are completed,
+ and the result will be stored in a file called
+ <c>cross_cover.html</c> in the <c>run.&lt;timestamp&gt;</c>
+ directory of the test the modules belong to.</p>
+ <p>Note that the function can be executed on any node, and it
+ does not require <c>test_server_ctrl</c> to be started first.</p>
+ <p>The <c>cross</c> statement in the cover file must be like this:</p>
+ <code type="none">
+{cross,[{Tag,Modules}]}.</code>
+ <p>where <c>Tag</c> is the same as <c>Tag</c> in the
+ <c>Tests</c> parameter to this function and <c>Modules</c> is a
+ list of module names (atoms).</p>
+ <p><em>Example:</em></p>
+ <p>If the module <c>m1</c> belongs to system <c>s1</c> but is
+ heavily used also in the tests for another system <c>s2</c>,
+ then the cover files for the two systems' tests could be like
+ this:</p>
+<code type="none">
+s1.cover:
+ {include,[m1]}.
+
+s2.cover:
+ {include,[....]}. % modules belonging to system s2
+ {cross,[{s1,[m1]}]}.</code>
+ <p>When the tests for both <c>s1</c> and <c>s2</c> are completed, run</p>
+<code type="none">
+test_server_ctrl:cross_cover_analyse(Level,[{s1,S1LogDir},{s2,S2LogDir}])
+</code>
+
+ <p>and the accumulated cover data for <c>m1</c> will be written to
+ <c>S1LogDir/[run.&lt;timestamp&gt;/]cross_cover.html</c>.</p>
+ <p>Note that the <c>m1</c> module will also be presented in the
+ normal coverage log for <c>s1</c> (due to the include statement in
+ <c>s1.cover</c>), but that only includes the coverage achieved by the
+ <c>s1</c> test itself.</p>
+ <p>The Tag in the <c>cross</c> statement in the cover file has
+ no other purpose than mapping the list of modules
+ (<c>[m1]</c> in the example above) to the correct log
+ directory where it should be included in the
+ <c>cross_cover.html</c> file (<c>S1LogDir</c> in the example
+ above). I.e. the value of <c>Tag</c> has no meaning, it
+ could be <c>foo</c> as well as <c>s1</c> above, as long as
+ the same <c>Tag</c> is used in the cover file and in the
+ call to this function.</p>
</desc>
</func>
<func>
diff --git a/lib/test_server/doc/src/ts.xml b/lib/test_server/doc/src/ts.xml
index 4a2c536e96..82ba3a5017 100644
--- a/lib/test_server/doc/src/ts.xml
+++ b/lib/test_server/doc/src/ts.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2007</year>
- <year>2011</year>
+ <year>2012</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -450,7 +450,7 @@ This option is mandatory for remote targets
<desc>
<p>Analyse cover data collected from all tests.
</p>
- <p>See test_server_ctrl:cross_cover_analyse/1
+ <p>See test_server_ctrl:cross_cover_analyse/2
</p>
</desc>
</func>
diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile
index 20e7a5942c..3261936472 100644
--- a/lib/test_server/src/Makefile
+++ b/lib/test_server/src/Makefile
@@ -69,7 +69,6 @@ INTERNAL_HRL_FILES = test_server_internal.hrl
TS_HRL_FILES= ts.hrl
C_FILES =
AUTOCONF_FILES = configure.in conf_vars.in
-COVER_FILES = cross.cover
PROGRAMS = configure config.sub config.guess install-sh
CONFIG = ts.config ts.unix.config ts.win32.config
@@ -137,7 +136,7 @@ release_tests_spec: opt
$(INSTALL_DATA) $(ERL_FILES) $(TS_ERL_FILES) \
$(HRL_FILES) $(INTERNAL_HRL_FILES) $(TS_HRL_FILES) \
$(TS_TARGET_FILES) \
- $(AUTOCONF_FILES) $(C_FILES) $(COVER_FILES) $(CONFIG) \
+ $(AUTOCONF_FILES) $(C_FILES) $(CONFIG) \
"$(RELEASE_PATH)/test_server"
$(INSTALL_SCRIPT) $(PROGRAMS) "$(RELEASE_PATH)/test_server"
diff --git a/lib/test_server/src/erl2html2.erl b/lib/test_server/src/erl2html2.erl
index 9c459c05d4..1729257809 100644
--- a/lib/test_server/src/erl2html2.erl
+++ b/lib/test_server/src/erl2html2.erl
@@ -34,11 +34,17 @@ convert(File, Dest) ->
%%
%% FIXME: The colours should *really* be set with
%% stylesheets...
+ Encoding = encoding(File),
Header = ["<!DOCTYPE HTML PUBLIC "
"\"-//W3C//DTD HTML 3.2 Final//EN\">\n"
"<!-- autogenerated by '"++atom_to_list(?MODULE)++"'. -->\n"
"<html>\n"
- "<head><title>", File, "</title></head>\n\n"
+ "<head>\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html;"
+ "charset=",
+ Encoding,"\"/>\n"
+ "<title>", File, "</title>\n"
+ "</head>\n\n"
"<body bgcolor=\"white\" text=\"black\""
" link=\"blue\" vlink=\"purple\" alink=\"red\">\n"],
convert(File, Dest, Header).
@@ -55,12 +61,12 @@ convert(File, Dest, Header) ->
case file:open(Dest,[write,raw]) of
{ok,DFd} ->
file:write(DFd,[Header,"<pre>\n"]),
- Lines = build_html(SFd,DFd,Functions),
+ _Lines = build_html(SFd,DFd,Functions),
file:write(DFd,["</pre>\n",footer(),
"</body>\n</html>\n"]),
%% {_, Time2} = statistics(runtime),
%% io:format("Converted ~p lines in ~.2f Seconds.~n",
- %% [Lines, Time2/1000]),
+ %% [_Lines, Time2/1000]),
file:close(SFd),
file:close(DFd),
ok;
@@ -180,3 +186,20 @@ possibly_enhance(Str,false) ->
%%% End of the file
footer() ->
"".
+
+%%%-----------------------------------------------------------------
+%%% Read encoding from source file
+encoding(File) ->
+ Encoding =
+ case epp:read_encoding(File) of
+ none ->
+ epp:default_encoding();
+ E ->
+ E
+ end,
+ html_encoding(Encoding).
+
+html_encoding(latin1) ->
+ "iso-8859-1";
+html_encoding(utf8) ->
+ "utf-8".
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index 14cdfd391a..37cd8fac99 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -60,8 +60,6 @@
-include("test_server_internal.hrl").
-include_lib("kernel/include/file.hrl").
--define(pl2a(M), test_server_sup:package_atom(M)).
-
init_target_info() ->
[$.|Emu] = code:objfile_extension(),
{_, OTPRel} = init:script_id(),
@@ -97,7 +95,8 @@ init_purify() ->
%% is found, else {error,application_not_found}.
cover_compile({none,_Exclude,Include,Cross}) ->
- CompileMods = Include++Cross,
+ CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross),
+ CompileMods = Include++CrossMods,
case length(CompileMods) of
0 ->
io:fwrite("WARNING: No modules to cover compile!\n\n",[]),
@@ -111,7 +110,8 @@ cover_compile({none,_Exclude,Include,Cross}) ->
{ok,Include}
end;
cover_compile({App,all,Include,Cross}) ->
- CompileMods = Include++Cross,
+ CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross),
+ CompileMods = Include++CrossMods,
case length(CompileMods) of
0 ->
io:fwrite("WARNING: No modules to cover compile!\n\n",[]),
@@ -129,9 +129,10 @@ cover_compile({App,all,Include,Cross}) ->
{ok,Include}
end;
cover_compile({App,Exclude,Include,Cross}) ->
+ CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross),
case code:lib_dir(App) of
{error,bad_name} ->
- case Include++Cross of
+ case Include++CrossMods of
[] ->
io:format("\nWARNING: Can't find lib_dir for \'~w\'\n"
"Not cover compiling!\n\n",[App]),
@@ -152,7 +153,7 @@ cover_compile({App,Exclude,Include,Cross}) ->
WC = filename:join(EbinDir,"*.beam"),
AllMods = module_names(filelib:wildcard(WC)),
AnalyseMods = (AllMods ++ Include) -- Exclude,
- CompileMods = AnalyseMods ++ Cross,
+ CompileMods = AnalyseMods ++ CrossMods,
case length(CompileMods) of
0 ->
io:fwrite("WARNING: No modules to cover compile!\n\n",[]),
@@ -317,14 +318,21 @@ pmap(Fun,List) ->
do_cover_for_node(Node,CoverFunc) ->
+ do_cover_for_node(Node,CoverFunc,true).
+do_cover_for_node(Node,CoverFunc,StickUnstick) ->
%% In case a slave node is starting another slave node! I.e. this
%% function is executed on a slave node - then the cover function
%% must be executed on the master node. This is for instance the
%% case in test_server's own tests.
MainCoverNode = cover:get_main_node(),
- Sticky = unstick_all_sticky(MainCoverNode,Node),
+ Sticky =
+ if StickUnstick -> unstick_all_sticky(MainCoverNode,Node);
+ true -> ok
+ end,
rpc:call(MainCoverNode,cover,CoverFunc,[Node]),
- stick_all_sticky(Node,Sticky).
+ if StickUnstick -> stick_all_sticky(Node,Sticky);
+ true -> ok
+ end.
unstick_all_sticky(Node) ->
unstick_all_sticky(node(),Node).
@@ -911,7 +919,7 @@ run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit,
put(test_server_logopts, LogOpts),
Where = [{Mod,Func}],
put(test_server_loc, Where),
- FWInitResult = test_server_sup:framework_call(init_tc,[?pl2a(Mod),Func,Args0],
+ FWInitResult = test_server_sup:framework_call(init_tc,[Mod,Func,Args0],
{ok,Args0}),
set_tc_state(running),
{{Time,Value},Loc,Opts} =
@@ -1045,7 +1053,7 @@ do_end_tc_call(Mod, Func, Res, Return) ->
Ref = make_ref(),
if FwMod == "ct_framework" ; FwMod == "undefined"; FwMod == false ->
case test_server_sup:framework_call(
- end_tc, [?pl2a(Mod),Func,Res, Return], ok) of
+ end_tc, [Mod,Func,Res, Return], ok) of
{fail,FWReason} ->
{failed,FWReason};
ok ->
@@ -1060,7 +1068,7 @@ do_end_tc_call(Mod, Func, Res, Return) ->
end;
true ->
case test_server_sup:framework_call(FwMod, end_tc,
- [?pl2a(Mod),Func,Res], Ref) of
+ [Mod,Func,Res], Ref) of
{fail,FWReason} ->
{failed,FWReason};
_Else ->
@@ -1294,11 +1302,11 @@ get_loc(Pid) ->
fw_error_notify(Mod, Func, Args, Error) ->
test_server_sup:framework_call(error_notification,
- [?pl2a(Mod),Func,[Args],
+ [Mod,Func,[Args],
{Error,unknown}]).
fw_error_notify(Mod, Func, Args, Error, Loc) ->
test_server_sup:framework_call(error_notification,
- [?pl2a(Mod),Func,[Args],
+ [Mod,Func,[Args],
{Error,Loc}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2186,12 +2194,9 @@ start_node(Name, Type, Options) ->
%% Cannot run cover on shielded node or on a node started
%% by a shielded node.
- Cover = case is_cover() of
+ Cover = case is_cover(Node) of
true ->
- not is_shielded(Name)
- andalso same_version(Node)
- andalso proplists:get_value(start_cover,Options,
- true);
+ proplists:get_value(start_cover,Options,true);
false ->
false
end,
@@ -2230,15 +2235,8 @@ wait_for_node(Slave) ->
Result = receive {sync_result,R} -> R end,
case Result of
ok ->
- Cover = case is_cover() of
- true ->
- not is_shielded(Slave) andalso same_version(Slave);
- false ->
- false
- end,
-
net_adm:ping(Slave),
- case Cover of
+ case is_cover(Slave) of
true ->
do_cover_for_node(Slave,start);
_ ->
@@ -2256,12 +2254,9 @@ wait_for_node(Slave) ->
%% Kills a (remote) node.
%% Also inform test_server_ctrl so it can clean up!
stop_node(Slave) ->
- Nocover = is_shielded(Slave) orelse not same_version(Slave),
- case is_cover() of
- true when not Nocover ->
- do_cover_for_node(Slave,flush);
- _ ->
- ok
+ Cover = is_cover(Slave),
+ if Cover -> do_cover_for_node(Slave,flush,false);
+ true -> ok
end,
group_leader() ! {sync_apply,self(),{test_server_ctrl,stop_node,[Slave]}},
Result = receive {sync_result,R} -> R end,
@@ -2273,10 +2268,15 @@ stop_node(Slave) ->
{nodedown, Slave} ->
format(minor, "Stopped slave node: ~p", [Slave]),
format(major, "=node_stop ~p", [Slave]),
+ if Cover -> do_cover_for_node(Slave,stop,false);
+ true -> ok
+ end,
true
after 30000 ->
format("=== WARNING: Node ~p does not seem to terminate.",
[Slave]),
+ erlang:monitor_node(Slave, false),
+ receive {nodedown, Slave} -> ok after 0 -> ok end,
false
end;
{error, _Reason} ->
@@ -2288,9 +2288,27 @@ stop_node(Slave) ->
[Slave]),
case net_adm:ping(Slave)of
pong ->
+ erlang:monitor_node(Slave, true),
slave:stop(Slave),
- true;
+ receive
+ {nodedown, Slave} ->
+ format(minor, "Stopped slave node: ~p", [Slave]),
+ format(major, "=node_stop ~p", [Slave]),
+ if Cover -> do_cover_for_node(Slave,stop,false);
+ true -> ok
+ end,
+ true
+ after 30000 ->
+ format("=== WARNING: Node ~p does not seem to terminate.",
+ [Slave]),
+ erlang:monitor_node(Slave, false),
+ receive {nodedown, Slave} -> ok after 0 -> ok end,
+ false
+ end;
pang ->
+ if Cover -> do_cover_for_node(Slave,stop,false);
+ true -> ok
+ end,
false
end
end.
@@ -2377,6 +2395,14 @@ same_version(Name) ->
OtherVersion = rpc:call(Name, erlang, system_info, [version]),
ThisVersion =:= OtherVersion.
+is_cover(Name) ->
+ case is_cover() of
+ true ->
+ not is_shielded(Name) andalso same_version(Name);
+ false ->
+ false
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% temp_name(Stem) -> string()
%% Stem = string()
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index bc08c12089..c5c57426b4 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -53,8 +53,7 @@
-export([reject_io_reqs/1, get_levels/0, set_levels/3]).
-export([multiply_timetraps/1, scale_timetraps/1, get_timetrap_parameters/0]).
-export([create_priv_dir/1]).
--export([cover/2, cover/3, cover/8,
- cross_cover_analyse/2, cross_cover_analyse/3, trc/1, stop_trace/0]).
+-export([cover/2, cover/3, cover/8, cross_cover_analyse/2, trc/1, stop_trace/0]).
-export([testcase_callback/1]).
-export([set_random_seed/1]).
-export([kill_slavenodes/0]).
@@ -88,17 +87,18 @@
-define(data_dir_suffix, "_data/").
-define(suitelog_name, "suite.log").
-define(coverlog_name, "cover.html").
+-define(raw_coverlog_name, "cover.log").
-define(cross_coverlog_name, "cross_cover.html").
+-define(raw_cross_coverlog_name, "cross_cover.log").
+-define(cross_cover_info, "cross_cover.info").
-define(cover_total, "total_cover.log").
-define(unexpected_io_log, "unexpected_io.log").
-define(last_file, "last_name").
-define(last_link, "last_link").
-define(last_test, "last_test").
-define(html_ext, ".html").
--define(cross_cover_file, "cross.cover").
-define(now, erlang:now()).
--define(pl2a(M), test_server_sup:package_atom(M)).
-define(void_fun, fun() -> ok end).
-define(mod_result(X), if X == skip -> skipped;
X == auto_skip -> skipped;
@@ -409,7 +409,9 @@ cover(CoverFile, Analyse) ->
cover(App, CoverFile, Analyse) ->
controller_call({cover,{App,CoverFile},Analyse,true}).
cover(App, CoverFile, Exclude, Include, Cross, Export, Analyse, Stop) ->
- controller_call({cover,{App,{CoverFile,Exclude,Include,Cross,Export}},Analyse,Stop}).
+ controller_call({cover,
+ {App,{CoverFile,Exclude,Include,Cross,Export}},
+ Analyse,Stop}).
testcase_callback(ModFunc) ->
controller_call({testcase_callback,ModFunc}).
@@ -2277,7 +2279,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
set_io_buffering(undefined),
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode),
test_server_sup:framework_call(report, [tc_auto_skip,
- {?pl2a(Mod),Func,Comment}]),
+ {Mod,Func,Comment}]),
run_test_cases_loop(Cases, Config, TimetrapData, ParentMode,
delete_status(Ref, Status));
_ ->
@@ -2286,7 +2288,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
wait_for_cases(Ref),
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode),
test_server_sup:framework_call(report, [tc_auto_skip,
- {?pl2a(Mod),Func,Comment}]),
+ {Mod,Func,Comment}]),
case CurrIOHandler of
{Ref,_} ->
%% current_io_handler was set by start conf of this
@@ -2303,7 +2305,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
%% this is a skipped end conf for a non-parallel group that's not
%% nested under a parallel group
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode),
- test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]),
%% Check if this group is auto skipped because of error in the init conf.
%% If so, check if the parent group is a sequence, and if it is, skip
@@ -2334,7 +2336,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
%% this is a skipped end conf for a non-parallel group nested under
%% a parallel group (io buffering is active)
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode),
- test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]),
case CurrIOHandler of
{Ref,_} ->
%% current_io_handler was set by start conf of this
@@ -2350,7 +2352,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
%% this is a skipped start conf for a group which is not nested
%% under a parallel group
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode),
- test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]),
run_test_cases_loop(Cases, Config, TimetrapData, [conf(Ref,[])|Mode], Status);
{_,Ref0} when is_reference(Ref0) ->
%% this is a skipped start conf for a group nested under a parallel group
@@ -2361,7 +2363,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases],
ok
end,
{Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode),
- test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]),
run_test_cases_loop(Cases, Config, TimetrapData, [conf(Ref,[])|Mode], Status)
end;
@@ -2369,7 +2371,7 @@ run_test_cases_loop([{auto_skip_case,{Case,Comment},SkipMode}|Cases],
Config, TimetrapData, Mode, Status) ->
{Mod,Func} = skip_case(auto, undefined, get(test_server_case_num)+1,
Case, Comment, is_io_buffered(), SkipMode),
- test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]),
run_test_cases_loop(Cases, Config, TimetrapData, Mode,
update_status(skipped, Mod, Func, Status));
@@ -2385,7 +2387,7 @@ run_test_cases_loop([{skip_case,{conf,Ref,Case,Comment}}|Cases0],
%% skipped start conf
{skip_cases_upto(Ref, Cases0, Comment, conf, Mode),Config}
end,
- test_server_sup:framework_call(report, [tc_user_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_user_skip,{Mod,Func,Comment}]),
run_test_cases_loop(Cases, Config1, TimetrapData, Mode,
update_status(skipped, Mod, Func, Status));
@@ -2393,7 +2395,7 @@ run_test_cases_loop([{skip_case,{Case,Comment}}|Cases],
Config, TimetrapData, Mode, Status) ->
{Mod,Func} = skip_case(user, undefined, get(test_server_case_num)+1,
Case, Comment, is_io_buffered()),
- test_server_sup:framework_call(report, [tc_user_skip,{?pl2a(Mod),Func,Comment}]),
+ test_server_sup:framework_call(report, [tc_user_skip,{Mod,Func,Comment}]),
run_test_cases_loop(Cases, Config, TimetrapData, Mode,
update_status(skipped, Mod, Func, Status));
@@ -3571,7 +3573,7 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit,
end,
test_server_sup:framework_call(report,
- [tc_start,{{?pl2a(Mod),Func},MinorName}]),
+ [tc_start,{{Mod,Func},MinorName}]),
print_props((RunInit==skip_init), get_props(Mode)),
GroupName = case get_name(Mode) of
@@ -3756,7 +3758,7 @@ progress(skip, CaseNum, Mod, Func, Loc, Reason, Time,
print(major, "=result skipped", []),
print(1, "*** SKIPPED *** ~s",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
- test_server_sup:framework_call(report, [tc_done,{?pl2a(Mod),Func,
+ test_server_sup:framework_call(report, [tc_done,{Mod,Func,
{skipped,Reason1}}]),
ReasonStr = reason_to_string(Reason1),
ReasonStr1 = lists:flatten([string:strip(S,left) ||
@@ -3787,7 +3789,7 @@ progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T,
print(1, "*** FAILED *** ~s",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
test_server_sup:framework_call(report,
- [tc_done,{?pl2a(Mod),Func,
+ [tc_done,{Mod,Func,
{failed,timetrap_timeout}}]),
FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)),
ErrorReason = io_lib:format("{timetrap_timeout,~s}", [FormatLastLoc]),
@@ -3813,7 +3815,7 @@ progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T,
print(1, "*** FAILED *** ~s",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
test_server_sup:framework_call(report,
- [tc_done,{?pl2a(Mod),Func,
+ [tc_done,{Mod,Func,
{failed,testcase_aborted}}]),
FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)),
ErrorReason = io_lib:format("{testcase_aborted,~s}", [FormatLastLoc]),
@@ -3838,7 +3840,7 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time,
print(major, "=result failed: ~p, ~p", [Reason,unknown]),
print(1, "*** FAILED *** ~s",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
- test_server_sup:framework_call(report, [tc_done,{?pl2a(Mod),Func,
+ test_server_sup:framework_call(report, [tc_done,{Mod,Func,
{failed,Reason}}]),
TimeStr = io_lib:format(if is_float(Time) -> "~.3fs";
true -> "~w"
@@ -3874,7 +3876,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time,
print(major, "=result failed: ~p, ~p", [Reason,Loc]),
print(1, "*** FAILED *** ~s",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
- test_server_sup:framework_call(report, [tc_done,{?pl2a(Mod),Func,
+ test_server_sup:framework_call(report, [tc_done,{Mod,Func,
{failed,Reason}}]),
TimeStr = io_lib:format(if is_float(Time) -> "~.3fs";
true -> "~w"
@@ -3899,7 +3901,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time,
progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time,
Comment0, {St0,St1}) ->
print(minor, "successfully completed test case", []),
- test_server_sup:framework_call(report, [tc_done,{?pl2a(Mod),Func,ok}]),
+ test_server_sup:framework_call(report, [tc_done,{Mod,Func,ok}]),
Comment =
case RetVal of
{comment,RetComment} ->
@@ -4546,7 +4548,7 @@ collect_case_invoke(Mod, Case, MFA, St) ->
end;
_ ->
Suite = test_server_sup:framework_call(get_suite,
- [?pl2a(Mod),Case],
+ [Mod,Case],
[]),
collect_subcases(Mod, Case, MFA, St, Suite)
end.
@@ -4898,33 +4900,52 @@ pinfo(P) ->
%% - it does not belong to the application, but is listed in the
%% {include,List} part of the App.cover file
%% - it does not belong to the application, but is listed in the
-%% cross.cover file (in the test_server application) under 'all'
-%% or under the tested application.
-%%
-%% The modules listed in the cross.cover file are modules that are
-%% hevily used by other applications than the one they belong
-%% to. After all tests are completed, these modules can be analysed
-%% with coverage data from all tests - see cross_cover_analyse/1. The
-%% result is stored in a file called cross_cover.html in the
-%% run.<timestamp> directory of the application the modules belong
-%% to.
-%%
-%% For example, the lists module is listed in cross.cover to be
-%% included in all tests. lists belongs to the stdlib
-%% application. cross_cover_analyse/1 will create a file named
-%% cross_cover.html under the newest stdlib.logs/run.xxx directory,
-%% where the coverage result for the lists module from all tests is
-%% presented.
-%%
-%% The lists module is also presented in the normal coverage log
-%% for stdlib, but that only includes the coverage achieved by
-%% the stdlib tests themselves.
-%%
-%% The Cross cover file cross.cover contains elements like this:
-%% {App,Modules}.
-%% where App can be an application name or the atom all. The
-%% application (or all applications) shall cover compile the listed
-%% Modules.
+%% {cross,[{Tag,List}]} part of the App.cover file
+%%
+%% The modules listed in the 'cross' part of the cover file are
+%% modules that are heavily used by other tests than the one where
+%% they are explicitly tested. They should then be listed as 'cross'
+%% in the cover file for the test where they are used but do not
+%% belong.
+%%
+%% After all tests are completed, the these modules can be analysed
+%% with coverage data from all tests where they are compiled - see
+%% cross_cover_analyse/2. The result is stored in a file called
+%% cross_cover.html in the run.<timestamp> directory of the
+%% test the modules belong to.
+%%
+%% Example:
+%% If the module m1 belongs to system s1 but is heavily used also in
+%% the tests for another system s2, then the cover files for the two
+%% systems could be like this:
+%%
+%% s1.cover:
+%% {include,[m1]}.
+%%
+%% s2.cover:
+%% {include,[....]}. % modules belonging to system s2
+%% {cross,[{s1,[m1]}]}.
+%%
+%% When the tests for both s1 and s2 are completed, run
+%% cross_cover_analyse(Level,[{s1,S1LogDir},{s2,S2LogDir}]), and
+%% the accumulated cover data for m1 will be written to
+%% S1LogDir/[run.<timestamp>/]cross_cover.html
+%%
+%% S1LogDir and S2LogDir are either the run.<timestamp> directories
+%% for the two tests, or the parent directory of these, in which case
+%% the latest run.<timestamp> directory will be chosen.
+%%
+%% Note that the m1 module will also be presented in the normal
+%% coverage log for s1 (due to the include statement in s1.cover), but
+%% that only includes the coverage achieved by the s1 test itself.
+%%
+%% The Tag in the 'cross' statement in the cover file has no other
+%% purpose than mapping the list of modules ([m1] in the example
+%% above) to the correct log directory where it should be included in
+%% the cross_cover.html file (S1LogDir in the example above).
+%% I.e. the value of the Tag has no meaning, it could be foo as well
+%% as s1 above, as long as the same Tag is used in the cover file and
+%% in the call to cross_cover_analyse/2.
%% Cover compilation
@@ -4933,8 +4954,7 @@ cover_compile({App,{_File,Exclude,Include,Cross,_Export}}) ->
cover_compile1({App,Exclude,Include,Cross});
cover_compile({App,CoverFile}) ->
- Cross = get_cross_modules(App),
- {Exclude,Include} = read_cover_file(CoverFile),
+ {Exclude,Include,Cross} = read_cover_file(CoverFile),
cover_compile1({App,Exclude,Include,Cross}).
cover_compile1(What) ->
@@ -4945,41 +4965,57 @@ cover_compile1(What) ->
%% (Exclude), and a list of modules that are not members of the
%% application but shall be compiled (Include).
read_cover_file(none) ->
- {[],[]};
+ {[],[],[]};
read_cover_file(CoverFile) ->
case file:consult(CoverFile) of
{ok,List} ->
- case check_cover_file(List, [], []) of
- {ok,Exclude,Include} -> {Exclude,Include};
+ case check_cover_file(List, [], [], []) of
+ {ok,Exclude,Include,Cross} -> {Exclude,Include,Cross};
error ->
io:fwrite("Faulty format of CoverFile ~p\n", [CoverFile]),
- {[],[]}
+ {[],[],[]}
end;
{error,Reason} ->
io:fwrite("Can't read CoverFile ~p\nReason: ~p\n",
[CoverFile,Reason]),
- {[],[]}
+ {[],[],[]}
end.
-check_cover_file([{exclude,all}|Rest], _, Include) ->
- check_cover_file(Rest, all, Include);
-check_cover_file([{exclude,Exclude}|Rest], _, Include) ->
+check_cover_file([{exclude,all}|Rest], _, Include, Cross) ->
+ check_cover_file(Rest, all, Include, Cross);
+check_cover_file([{exclude,Exclude}|Rest], _, Include, Cross) ->
case lists:all(fun(M) -> is_atom(M) end, Exclude) of
true ->
- check_cover_file(Rest, Exclude, Include);
+ check_cover_file(Rest, Exclude, Include, Cross);
false ->
error
end;
-check_cover_file([{include,Include}|Rest], Exclude, _) ->
+check_cover_file([{include,Include}|Rest], Exclude, _, Cross) ->
case lists:all(fun(M) -> is_atom(M) end, Include) of
true ->
- check_cover_file(Rest, Exclude, Include);
+ check_cover_file(Rest, Exclude, Include, Cross);
false ->
error
end;
-check_cover_file([], Exclude, Include) ->
- {ok,Exclude,Include}.
+check_cover_file([{cross,Cross}|Rest], Exclude, Include, _) ->
+ case check_cross(Cross) of
+ true ->
+ check_cover_file(Rest, Exclude, Include, Cross);
+ false ->
+ error
+ end;
+check_cover_file([], Exclude, Include, Cross) ->
+ {ok,Exclude,Include,Cross}.
+check_cross([{Tag,Modules}|Rest]) ->
+ case lists:all(fun(M) -> is_atom(M) end, [Tag|Modules]) of
+ true ->
+ check_cross(Rest);
+ false ->
+ false
+ end;
+check_cross([]) ->
+ true.
%% Cover analysis, per application
@@ -5000,16 +5036,17 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) ->
"<p><a href=\"~s\">Coverdata collected over all tests</a></p>",
[?cross_coverlog_name]),
- {CoverFile,_Included,Excluded} =
+ {CoverFile,_Included,Excluded,Cross} =
case CoverInfo of
- {File,Excl,Incl,_Cross,Export} ->
+ {File,Excl,Incl,Cr,Export} ->
cover:export(Export),
- {File,Incl,Excl};
+ {File,Incl,Excl,Cr};
File ->
- {Excl,Incl} = read_cover_file(File),
- {File,Incl,Excl}
+ {Excl,Incl,Cr} = read_cover_file(File),
+ {File,Incl,Excl,Cr}
end,
io:fwrite(CoverLog, "<p>CoverFile: <code>~p</code>\n", [CoverFile]),
+ write_cross_cover_info(TestDir,Cross),
case length(cover:imported_modules()) of
Imps when Imps > 0 ->
@@ -5022,6 +5059,8 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) ->
io:fwrite(CoverLog, "<p>Excluded module(s): <code>~p</code>\n", [Excluded]),
Coverage = cover_analyse(Analyse, AnalyseMods, Stop),
+ file:write_file(filename:join(TestDir,?raw_coverlog_name),
+ term_to_binary(Coverage)),
case lists:filter(fun({_M,{_,_,_}}) -> false;
(_) -> true
@@ -5043,20 +5082,20 @@ cover_analyse(Analyse, AnalyseMods, Stop) ->
test_server:cover_analyse({Analyse,TestDir}, AnalyseMods, Stop).
-%% Cover analysis, cross application
+%% Cover analysis - accumulated over multiple tests
%% This can be executed on any node after all tests are finished.
-%% Apps = [{App,Dir}]
-%% App = atom(), application name
-%% Dir = string(), the log directory for App, normally where
-%% run.<timestamp> is found.
-%% Modules = [atom()], modules that have been cover compiled during tests
-%% of other apps than the one they belong to.
-cross_cover_analyse(Analyse, Apps) ->
- cross_cover_analyse(Analyse, Apps, get_cross_modules()).
-cross_cover_analyse(Analyse, Apps, Modules) ->
- Apps1 = get_latest_run_dirs(Apps),
- Apps2 = add_cross_modules(Modules,Apps1),
- CoverdataFiles = get_coverdata_files(Apps2),
+%% Analyse = overview | details
+%% TagDirs = [{Tag,Dir}]
+%% Tag = atom(), identifier
+%% Dir = string(), the log directory for Tag, it can be a
+%% run.<timestamp> directory or the parent directory of
+%% such (in which case the latest run.<timestamp> directory
+%% is used)
+cross_cover_analyse(Analyse, TagDirs0) ->
+ TagDirs = get_latest_run_dirs(TagDirs0),
+ TagMods = get_all_cross_info(TagDirs,[]),
+ TagDirMods = add_cross_modules(TagMods,TagDirs),
+ CoverdataFiles = get_coverdata_files(TagDirMods),
lists:foreach(fun(CDF) -> cover:import(CDF) end, CoverdataFiles),
io:fwrite("Cover analysing...\n", []),
DetailsFun =
@@ -5066,39 +5105,52 @@ cross_cover_analyse(Analyse, Apps, Modules) ->
OutFile = filename:join(Dir,
atom_to_list(M) ++
".CROSS_COVER.html"),
- cover:analyse_to_file(M, OutFile, [html]),
- {file,OutFile}
+ case cover:analyse_to_file(M, OutFile, [html]) of
+ {ok,_} ->
+ {file,OutFile};
+ Error ->
+ Error
+ end
end;
_ ->
fun(_,_) -> undefined end
end,
- Coverage = analyse_apps(Apps2, DetailsFun, []),
+ Coverage = analyse_tests(TagDirMods, DetailsFun, []),
cover:stop(),
- write_cross_cover_logs(Coverage,Apps2).
+ write_cross_cover_logs(Coverage,TagDirMods).
-%% For each application from which there are cross cover analysed
+write_cross_cover_info(_Dir,[]) ->
+ ok;
+write_cross_cover_info(Dir,Cross) ->
+ {ok,Fd} = file:open(filename:join(Dir,?cross_cover_info),[write]),
+ lists:foreach(fun(C) -> io:format(Fd,"~p.~n",[C]) end, Cross),
+ file:close(Fd).
+
+%% For each test from which there are cross cover analysed
%% modules, write a cross cover log (cross_cover.html).
-write_cross_cover_logs([{App,Coverage}|T],Apps) ->
- case lists:keyfind(App,1,Apps) of
+write_cross_cover_logs([{Tag,Coverage}|T],TagDirMods) ->
+ case lists:keyfind(Tag,1,TagDirMods) of
{_,Dir,Mods} when Mods=/=[] ->
+ file:write_file(filename:join(Dir,?raw_cross_coverlog_name),
+ term_to_binary(Coverage)),
CoverLogName = filename:join(Dir,?cross_coverlog_name),
{ok,CoverLog} = file:open(CoverLogName, [write]),
write_coverlog_header(CoverLog),
io:fwrite(CoverLog,
"<h1>Coverage results for \'~w\' from all tests</h1>\n",
- [App]),
+ [Tag]),
write_cover_result_table(CoverLog, Coverage),
io:fwrite("Written file ~p\n", [CoverLogName]);
_ ->
ok
end,
- write_cross_cover_logs(T,Apps);
+ write_cross_cover_logs(T,TagDirMods);
write_cross_cover_logs([],_) ->
io:fwrite("done\n", []).
%% Get the latest run.<timestamp> directories
-get_latest_run_dirs([{App,Dir}|Apps]) ->
- [{App,get_latest_run_dir(Dir)} | get_latest_run_dirs(Apps)];
+get_latest_run_dirs([{Tag,Dir}|Rest]) ->
+ [{Tag,get_latest_run_dir(Dir)} | get_latest_run_dirs(Rest)];
get_latest_run_dirs([]) ->
[].
@@ -5117,44 +5169,47 @@ get_latest_dir([_|T],Latest) ->
get_latest_dir([],Latest) ->
Latest.
-%% Associate the cross cover modules with their applications.
-add_cross_modules(Mods,Apps)->
- do_add_cross_modules(Mods,[{App,Dir,[]} || {App,Dir} <- Apps]).
-do_add_cross_modules([Mod|Mods],Apps)->
- App = get_app(Mod),
- NewApps =
- case lists:keytake(App,1,Apps) of
- {value,{App,Dir,AppMods},Rest} ->
- [{App,Dir,lists:umerge([Mod],AppMods)}|Rest];
+get_all_cross_info([{_Tag,Dir}|Rest],Acc) ->
+ case file:consult(filename:join(Dir,?cross_cover_info)) of
+ {ok,TagMods} ->
+ get_all_cross_info(Rest,TagMods++Acc);
+ _ ->
+ get_all_cross_info(Rest,Acc)
+ end;
+get_all_cross_info([],Acc) ->
+ Acc.
+
+%% Associate the cross cover modules with their log directories
+add_cross_modules(TagMods,TagDirs)->
+ do_add_cross_modules(TagMods,[{Tag,Dir,[]} || {Tag,Dir} <- TagDirs]).
+do_add_cross_modules([{Tag,Mods1}|TagMods],TagDirMods)->
+ NewTagDirMods =
+ case lists:keytake(Tag,1,TagDirMods) of
+ {value,{Tag,Dir,Mods},Rest} ->
+ [{Tag,Dir,lists:umerge(lists:sort(Mods1),Mods)}|Rest];
false ->
- Apps
+ TagDirMods
end,
- do_add_cross_modules(Mods,NewApps);
-do_add_cross_modules([],Apps) ->
- %% Just to get the modules in the same order as app-only cover log
- [{App,Dir,lists:reverse(Mods)} || {App,Dir,Mods} <- Apps].
-
-get_app(Module) ->
- Beam = code:which(Module),
- AppDir = filename:basename(filename:dirname(filename:dirname(Beam))),
- [AppStr|_] = string:tokens(AppDir,"-"),
- list_to_atom(AppStr).
+ do_add_cross_modules(TagMods,NewTagDirMods);
+do_add_cross_modules([],TagDirMods) ->
+ %% Just to get the modules in the same order as in the normal cover log
+ [{Tag,Dir,lists:reverse(Mods)} || {Tag,Dir,Mods} <- TagDirMods].
%% Find all exported coverdata files.
-get_coverdata_files(Apps) ->
+get_coverdata_files(TagDirMods) ->
lists:flatmap(
- fun({_,LatestAppDir,_}) ->
- filelib:wildcard(filename:join(LatestAppDir,"all.coverdata"))
+ fun({_,LatestDir,_}) ->
+ filelib:wildcard(filename:join(LatestDir,"all.coverdata"))
end,
- Apps).
+ TagDirMods).
-%% For each application, analyse all modules
+%% For each test, analyse all modules
%% Used for cross cover analysis.
-analyse_apps([{App,LastTest,Modules}|T], DetailsFun, Acc) ->
+analyse_tests([{Tag,LastTest,Modules}|T], DetailsFun, Acc) ->
Cov = analyse_modules(LastTest, Modules, DetailsFun, []),
- analyse_apps(T, DetailsFun, [{App,Cov}|Acc]);
-analyse_apps([], _DetailsFun, Acc) ->
+ analyse_tests(T, DetailsFun, [{Tag,Cov}|Acc]);
+analyse_tests([], _DetailsFun, Acc) ->
Acc.
%% Analyse each module
@@ -5167,27 +5222,6 @@ analyse_modules(_Dir, [], _DetailsFun, Acc) ->
Acc.
-%% Read the cross cover file (cross.cover)
-get_cross_modules() ->
- get_cross_modules(all).
-get_cross_modules(App) ->
- case file:consult(?cross_cover_file) of
- {ok,List} ->
- get_cross_modules(App, List, []);
- _X ->
- []
- end.
-
-get_cross_modules(App, [{_To,Modules}|T], Acc) when App==all->
- get_cross_modules(App, T, Acc ++ Modules);
-get_cross_modules(App, [{To,Modules}|T], Acc) when To==App; To==all->
- get_cross_modules(App, T, Acc ++ Modules);
-get_cross_modules(App, [_H|T], Acc) ->
- get_cross_modules(App, T, Acc);
-get_cross_modules(_App, [], Acc) ->
- Acc.
-
-
%% Support functions for writing the cover logs (both cross and normal)
write_coverlog_header(CoverLog) ->
case catch
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl
index c7553cccb5..a6d426887e 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/test_server/src/test_server_sup.erl
@@ -28,7 +28,7 @@
get_username/0, get_os_family/0,
hostatom/0, hostatom/1, hoststr/0, hoststr/1,
framework_call/2,framework_call/3,framework_call/4,
- format_loc/1, package_str/1, package_atom/1,
+ format_loc/1,
call_trace/1]).
-include("test_server_internal.hrl").
-define(crash_dump_tar,"crash_dumps.tar.gz").
@@ -553,7 +553,7 @@ format_loc([{Mod,Func,Line}|Rest]) ->
format_loc([{Mod,LineOrFunc}]) ->
format_loc({Mod,LineOrFunc});
format_loc({Mod,Func}) when is_atom(Func) ->
- io_lib:format("{~s,~w}",[package_str(Mod),Func]);
+ io_lib:format("{~w,~w}",[Mod,Func]);
format_loc(Loc) ->
io_lib:format("~p",[Loc]).
@@ -562,15 +562,15 @@ format_loc1([{Mod,Func,Line}]) ->
format_loc1([{Mod,Func,Line}|Rest]) ->
[" ",format_loc1({Mod,Func,Line}),",\n"|format_loc1(Rest)];
format_loc1({Mod,Func,Line}) ->
- ModStr = package_str(Mod),
+ ModStr = atom_to_list(Mod),
case {lists:member(no_src, get(test_server_logopts)),
lists:reverse(ModStr)} of
{false,[$E,$T,$I,$U,$S,$_|_]} ->
- io_lib:format("{~s,~w,<a href=\"~s~s#~w\">~w</a>}",
- [ModStr,Func,downcase(ModStr),?src_listing_ext,
+ io_lib:format("{~w,~w,<a href=\"~s~s#~w\">~w</a>}",
+ [Mod,Func,downcase(ModStr),?src_listing_ext,
Line,Line]);
_ ->
- io_lib:format("{~s,~w,~w}",[ModStr,Func,Line])
+ io_lib:format("{~w,~w,~w}",[Mod,Func,Line])
end.
downcase(S) -> downcase(S, []).
@@ -581,22 +581,6 @@ downcase([C|Rest], Result) ->
downcase([], Result) ->
lists:reverse(Result).
-package_str(Mod) when is_atom(Mod) ->
- atom_to_list(Mod);
-package_str(Mod) when is_list(Mod), is_atom(hd(Mod)) ->
- %% convert [s1,s2] -> "s1.s2"
- [_|M] = lists:flatten(["."++atom_to_list(S) || S <- Mod]),
- M;
-package_str(Mod) when is_list(Mod) ->
- Mod.
-
-package_atom(Mod) when is_atom(Mod) ->
- Mod;
-package_atom(Mod) when is_list(Mod), is_atom(hd(Mod)) ->
- list_to_atom(package_str(Mod));
-package_atom(Mod) when is_list(Mod) ->
- list_to_atom(Mod).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% call_trace(TraceSpecFile) -> ok
%%
diff --git a/lib/test_server/src/ts.erl b/lib/test_server/src/ts.erl
index 115e783070..cfd7161dbd 100644
--- a/lib/test_server/src/ts.erl
+++ b/lib/test_server/src/ts.erl
@@ -160,8 +160,8 @@ help(installed) ->
" the given run options\n",
" ts:cross_cover_analyse(Level)\n"
" - Used after ts:run with option cover or \n"
- " cover_details. Analyses modules specified in\n"
- " cross.cover.\n"
+ " cover_details. Analyses modules specified with\n"
+ " a 'cross' statement in the cover spec file.\n"
" Level can be 'overview' or 'details'.\n",
" ts:compile_testcases()~n"
" ts:compile_testcases(Apps)~n"
@@ -528,8 +528,7 @@ cross_cover_analyse([Level]) ->
cross_cover_analyse(Level);
cross_cover_analyse(Level) ->
Apps = get_last_app_tests(),
- Modules = get_cross_modules(Apps,[]),
- test_server_ctrl:cross_cover_analyse(Level,Apps,Modules).
+ test_server_ctrl:cross_cover_analyse(Level,Apps).
get_last_app_tests() ->
AllTests = filelib:wildcard(filename:join(["*","*_test.logs"])),
@@ -558,30 +557,6 @@ get_last_app_tests([Dir|Dirs],RE,Acc) ->
get_last_app_tests([],_,Acc) ->
Acc.
-get_cross_modules([{App,_}|Apps],Acc) ->
- Mods = cross_modules(App),
- get_cross_modules(Apps,lists:umerge(Mods,Acc));
-get_cross_modules([],Acc) ->
- Acc.
-
-cross_modules(App) ->
- case default_coverfile(App) of
- none ->
- [];
- File ->
- case catch file:consult(File) of
- {ok,CoverSpec} ->
- case lists:keyfind(cross_apps,1,CoverSpec) of
- false ->
- [];
- {cross_apps,App,Modules} ->
- lists:usort(Modules)
- end;
- _ ->
- []
- end
- end.
-
%%% Implementation.
check_and_run(Fun) ->
diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl
index 95a3423fef..fb82a87fd0 100644
--- a/lib/test_server/test/test_server_SUITE.erl
+++ b/lib/test_server/test/test_server_SUITE.erl
@@ -80,7 +80,7 @@ all() ->
[test_server_SUITE, test_server_parallel01_SUITE,
test_server_conf02_SUITE, test_server_conf01_SUITE,
test_server_skip_SUITE, test_server_shuffle01_SUITE,
- test_server_break_SUITE].
+ test_server_break_SUITE, test_server_cover_SUITE].
%%--------------------------------------------------------------------
@@ -93,37 +93,95 @@ test_server_SUITE(Config) ->
% rpc:call(Node,dbg, tracer,[]),
% rpc:call(Node,dbg, p,[all,c]),
% rpc:call(Node,dbg, tpl,[test_server_ctrl,x]),
- run_test_server_tests("test_server_SUITE", 38, 1, 30,
- 19, 9, 1, 11, 2, 25, Config).
+ run_test_server_tests("test_server_SUITE",
+ [{test_server_SUITE,skip_case7,"SKIPPED!"}],
+ 38, 1, 30, 19, 9, 1, 11, 2, 25, Config).
test_server_parallel01_SUITE(Config) ->
- run_test_server_tests("test_server_parallel01_SUITE", 37, 0, 19,
- 19, 0, 0, 0, 0, 37, Config).
+ run_test_server_tests("test_server_parallel01_SUITE", [],
+ 37, 0, 19, 19, 0, 0, 0, 0, 37, Config).
test_server_shuffle01_SUITE(Config) ->
- run_test_server_tests("test_server_shuffle01_SUITE", 130, 0, 0,
- 76, 0, 0, 0, 0, 130, Config).
+ run_test_server_tests("test_server_shuffle01_SUITE", [],
+ 130, 0, 0, 76, 0, 0, 0, 0, 130, Config).
test_server_skip_SUITE(Config) ->
- run_test_server_tests("test_server_skip_SUITE", 3, 0, 1,
- 0, 0, 1, 3, 0, 0, Config).
+ run_test_server_tests("test_server_skip_SUITE", [],
+ 3, 0, 1, 0, 0, 1, 3, 0, 0, Config).
test_server_conf01_SUITE(Config) ->
- run_test_server_tests("test_server_conf01_SUITE", 24, 0, 12,
- 12, 0, 0, 0, 0, 24, Config).
+ run_test_server_tests("test_server_conf01_SUITE", [],
+ 24, 0, 12, 12, 0, 0, 0, 0, 24, Config).
test_server_conf02_SUITE(Config) ->
- run_test_server_tests("test_server_conf02_SUITE", 26, 0, 12,
- 12, 0, 0, 0, 0, 26, Config).
+ run_test_server_tests("test_server_conf02_SUITE", [],
+ 26, 0, 12, 12, 0, 0, 0, 0, 26, Config).
test_server_break_SUITE(Config) ->
- D = run_test_server_tests("test_server_break_SUITE", 8, 2, 6,
- 4, 0, 0, 0, 2, 6, Config),
- D.
+ run_test_server_tests("test_server_break_SUITE", [],
+ 8, 2, 6, 4, 0, 0, 0, 2, 6, Config).
-run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc,
+test_server_cover_SUITE(Config) ->
+ case test_server:is_cover() of
+ true ->
+ {skip, "Cover already running"};
+ false ->
+ PrivDir = ?config(priv_dir,Config),
+
+ %% Test suite has two test cases
+ %% tc1 calls cover_helper:foo/0
+ %% tc2 calls cover_helper:bar/0
+ %% Each function in cover_helper is one line.
+ %%
+ %% First test run skips tc2, so only cover_helper:foo/0 is executed.
+ %% Cover file specifies to include cover_helper in this test run.
+ CoverFile1 = filename:join(PrivDir,"t1.cover"),
+ CoverSpec1 = {include,[cover_helper]},
+ file:write_file(CoverFile1,io_lib:format("~p.~n",[CoverSpec1])),
+ run_test_server_tests("test_server_cover_SUITE",
+ [{test_server_cover_SUITE,tc2,"SKIPPED!"}],
+ 4, 0, 2, 1, 1, 0, 1, 0, 3,
+ CoverFile1, Config),
+
+ %% Next test run skips tc1, so only cover_helper:bar/0 is executed.
+ %% Cover file specifies cross compilation of cover_helper
+ CoverFile2 = filename:join(PrivDir,"t2.cover"),
+ CoverSpec2 = {cross,[{t1,[cover_helper]}]},
+ file:write_file(CoverFile2,io_lib:format("~p.~n",[CoverSpec2])),
+ run_test_server_tests("test_server_cover_SUITE",
+ [{test_server_cover_SUITE,tc1,"SKIPPED!"}],
+ 4, 0, 2, 1, 1, 0, 1, 0, 3, CoverFile2, Config),
+
+ %% Cross cover analyse
+ WorkDir = ?config(work_dir,Config),
+ WC = filename:join([WorkDir,"test_server_cover_SUITE.logs","run.*"]),
+ [D2,D1|_] = lists:reverse(lists:sort(filelib:wildcard(WC))),
+ TagDirs = [{t1,D1},{t2,D2}],
+ test_server_ctrl:cross_cover_analyse(details,TagDirs),
+
+ %% Check that cover log shows only what is really included
+ %% in the test and cross cover log show the accumulated
+ %% result.
+ {ok,Cover1} = file:read_file(filename:join(D1,"cover.log")),
+ [{cover_helper,{1,1,_}}] = binary_to_term(Cover1),
+ {ok,Cover2} = file:read_file(filename:join(D2,"cover.log")),
+ [] = binary_to_term(Cover2),
+ {ok,Cross} = file:read_file(filename:join(D1,"cross_cover.log")),
+ [{cover_helper,{2,0,_}}] = binary_to_term(Cross),
+ ok
+ end.
+
+
+run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc,
NUsrSkip, NAutoSkip,
NActualSkip, NActualFail, NActualSucc, Config) ->
+ run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc,
+ NUsrSkip, NAutoSkip,
+ NActualSkip, NActualFail, NActualSucc, false, Config).
+
+run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc,
+ NUsrSkip, NAutoSkip,
+ NActualSkip, NActualFail, NActualSucc, Cover, Config) ->
WorkDir = proplists:get_value(work_dir, Config),
ct:log("<a href=\"file://~s\">Test case log files</a>\n",
@@ -131,11 +189,17 @@ run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc,
Node = proplists:get_value(node, Config),
{ok,_Pid} = rpc:call(Node,test_server_ctrl, start, []),
+ case Cover of
+ false ->
+ ok;
+ _ ->
+ rpc:call(Node,test_server_ctrl,cover,[Cover,details])
+ end,
rpc:call(Node,
test_server_ctrl,add_dir_with_skip,
[SuiteName,
[proplists:get_value(data_dir,Config)],SuiteName,
- [{test_server_SUITE,skip_case7,"SKIPPED!"}]]),
+ Skip]),
until(fun() ->
rpc:call(Node,test_server_ctrl,jobs,[]) =:= []
diff --git a/lib/test_server/test/test_server_SUITE_data/Makefile.src b/lib/test_server/test/test_server_SUITE_data/Makefile.src
index ec8ddd78b0..c770627f04 100644
--- a/lib/test_server/test/test_server_SUITE_data/Makefile.src
+++ b/lib/test_server/test/test_server_SUITE_data/Makefile.src
@@ -5,4 +5,6 @@ all:
erlc test_server_shuffle01_SUITE.erl
erlc test_server_conf02_SUITE.erl
erlc test_server_skip_SUITE.erl
- erlc test_server_break_SUITE.erl \ No newline at end of file
+ erlc test_server_break_SUITE.erl
+ erlc test_server_cover_SUITE.erl
+ erlc +debug_info test_server_cover_SUITE_data/cover_helper.erl \ No newline at end of file
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl b/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl
index 70e30a3334..d9f009679a 100644
--- a/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl
+++ b/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl
@@ -41,7 +41,7 @@ init_per_suite(Config) ->
spawn(fun break_and_continue_sup/0),
Config.
-end_per_suite(Config) ->
+end_per_suite(_Config) ->
ok.
init_per_testcase(Case,Config) when Case==break_in_init_tc ->
@@ -90,19 +90,19 @@ break_in_end_tc_after_fail(Config) when is_list(Config) ->
break_in_end_tc_after_abort(Config) when is_list(Config) ->
?t:adjusted_sleep(2000). % will cause a timetrap timeout
-%%%-----------------------------------------------------------------
-%%% Internal functions
-
%% This test case checks that all breaks in previous test cases was
%% also continued, and that the break lasted as long as expected.
%% The reason for this is that some of the breaks above are in
%% end_per_testcase, and failures there will only produce a warning,
%% not an error - so this is to catch the error for real.
-check_all_breaks(Config) ->
+check_all_breaks(Config) when is_list(Config) ->
break_and_continue_sup ! {done,self()},
receive {Breaks,Continued} ->
check_all_breaks(Breaks,Continued)
end.
+%%%-----------------------------------------------------------------
+%%% Internal functions
+
check_all_breaks([{From,Case,T,Start}|Breaks],[{From,End}|Continued]) ->
Diff = timer:now_diff(End,Start),
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl b/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl
new file mode 100644
index 0000000000..b1ae70a302
--- /dev/null
+++ b/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl
@@ -0,0 +1,58 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(test_server_cover_SUITE).
+
+-export([all/1, init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+-export([tc1/1, tc2/1]).
+
+-include_lib("test_server/include/test_server.hrl").
+
+all(suite) ->
+ [tc1,tc2].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_testcase(_Case,Config) ->
+ Dog = ?t:timetrap({minutes,10}),
+ [{watchdog, Dog}|Config].
+
+end_per_testcase(_Case,Config) ->
+ Dog=?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%% Test cases
+tc1(Config) when is_list(Config) ->
+ cover_helper:foo(),
+ ok.
+
+tc2(Config) when is_list(Config) ->
+ cover_helper:bar(),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+
diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl b/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl
new file mode 100644
index 0000000000..6c74eb4e8a
--- /dev/null
+++ b/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl
@@ -0,0 +1,4 @@
+-module(cover_helper).
+-compile(export_all).
+foo() -> ok.
+bar() -> ok.
diff --git a/lib/test_server/test/test_server_test_lib.erl b/lib/test_server/test/test_server_test_lib.erl
index 4e89abf308..d466aa0110 100644
--- a/lib/test_server/test/test_server_test_lib.erl
+++ b/lib/test_server/test/test_server_test_lib.erl
@@ -83,14 +83,21 @@ start_slave(Config,_Level) ->
post_end_per_testcase(_TC, Config, Return, State) ->
Node = proplists:get_value(node, Config),
- case test_server:is_cover() of
- true ->
- cover:flush(Node);
- false ->
- ok
+ Cover = test_server:is_cover(),
+ if Cover-> cover:flush(Node);
+ true -> ok
end,
+ erlang:monitor_node(Node, true),
slave:stop(Node),
-
+ receive
+ {nodedown, Node} ->
+ if Cover -> cover:stop(Node);
+ true -> ok
+ end
+ after 5000 ->
+ erlang:monitor_node(Node, false),
+ receive {nodedown, Node} -> ok after 0 -> ok end %flush
+ end,
{Return, State}.
%% Parse an .suite log file
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 10f14b0a49..ab29d156aa 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -705,7 +705,9 @@ main_process_loop(State) ->
remote_collect('_',Nodes,true),
reply(From, ok),
Nodes1 = State#main_state.nodes--Nodes,
- main_process_loop(State#main_state{nodes=Nodes1});
+ LostNodes1 = State#main_state.lost_nodes--Nodes,
+ main_process_loop(State#main_state{nodes=Nodes1,
+ lost_nodes=LostNodes1});
{From, {flush,Nodes}} ->
remote_collect('_',Nodes,false),
@@ -792,8 +794,15 @@ main_process_loop(State) ->
{'DOWN', _MRef, process, {?SERVER,Node}, _Info} ->
%% A remote cover_server is down, mark as lost
- Nodes = State#main_state.nodes--[Node],
- Lost = [Node|State#main_state.lost_nodes],
+ {Nodes,Lost} =
+ case lists:member(Node,State#main_state.nodes) of
+ true ->
+ N = State#main_state.nodes--[Node],
+ L = [Node|State#main_state.lost_nodes],
+ {N,L};
+ false -> % node stopped
+ {State#main_state.nodes,State#main_state.lost_nodes}
+ end,
main_process_loop(State#main_state{nodes=Nodes,lost_nodes=Lost});
{nodeup,Node} ->
@@ -2087,30 +2096,40 @@ do_analyse_to_file(Module, OutFile, ErlFile, HTML) ->
case file:open(OutFile, [write]) of
{ok, OutFd} ->
if HTML ->
- io:format(OutFd,
- "<html>\n"
- "<head><title>~s</title></head>"
- "<body bgcolor=white text=black>\n"
- "<pre>\n",
- [OutFile]);
+ Encoding = encoding(ErlFile),
+ Header =
+ ["<!DOCTYPE HTML PUBLIC "
+ "\"-//W3C//DTD HTML 3.2 Final//EN\">\n"
+ "<html>\n"
+ "<head>\n"
+ "<meta http-equiv=\"Content-Type\""
+ " content=\"text/html; charset=",
+ Encoding,"\"/>\n"
+ "<title>",OutFile,"</title>\n"
+ "</head>"
+ "<body style='background-color: white;"
+ " color: black'>\n"
+ "<pre>\n"],
+ file:write(OutFd,Header);
true -> ok
end,
%% Write some initial information to the output file
{{Y,Mo,D},{H,Mi,S}} = calendar:local_time(),
- io:format(OutFd, "File generated from ~s by COVER "
- "~p-~s-~s at ~s:~s:~s~n",
- [ErlFile,
- Y,
- string:right(integer_to_list(Mo), 2, $0),
- string:right(integer_to_list(D), 2, $0),
- string:right(integer_to_list(H), 2, $0),
- string:right(integer_to_list(Mi), 2, $0),
- string:right(integer_to_list(S), 2, $0)]),
- io:format(OutFd, "~n"
- "**************************************"
- "**************************************"
- "~n~n", []),
+ Timestamp =
+ io_lib:format("~p-~s-~s at ~s:~s:~s",
+ [Y,
+ string:right(integer_to_list(Mo), 2, $0),
+ string:right(integer_to_list(D), 2, $0),
+ string:right(integer_to_list(H), 2, $0),
+ string:right(integer_to_list(Mi), 2, $0),
+ string:right(integer_to_list(S), 2, $0)]),
+ file:write(OutFd,
+ ["File generated from ",ErlFile," by COVER ",
+ Timestamp,"\n\n"
+ "**************************************"
+ "**************************************"
+ "\n\n"]),
print_lines(Module, InFd, OutFd, 1, HTML),
@@ -2405,3 +2424,20 @@ pmap(Fun, [], [], Limit, Cnt, Acc) ->
{'DOWN', _Ref, process, X, _} when is_pid(X) ->
pmap(Fun, [], [], Limit, Cnt - 1, Acc)
end.
+
+%%%-----------------------------------------------------------------
+%%% Read encoding from source file
+encoding(File) ->
+ Encoding =
+ case epp:read_encoding(File) of
+ none ->
+ epp:default_encoding();
+ E ->
+ E
+ end,
+ html_encoding(Encoding).
+
+html_encoding(latin1) ->
+ "iso-8859-1";
+html_encoding(utf8) ->
+ "utf-8".
diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl
index 989a661b75..70d62307c8 100644
--- a/lib/tools/src/lcnt.erl
+++ b/lib/tools/src/lcnt.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 3bf1b44af8..57260a3869 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -23,7 +23,9 @@
init_per_group/2,end_per_group/2]).
-export([start/1, compile/1, analyse/1, misc/1, stop/1,
- distribution/1, reconnect/1, die_and_reconnect/1, export_import/1,
+ distribution/1, reconnect/1, die_and_reconnect/1,
+ dont_reconnect_after_stop/1, stop_node_after_disconnect/1,
+ export_import/1,
otp_5031/1, eif/1, otp_5305/1, otp_5418/1, otp_6115/1, otp_7095/1,
otp_8188/1, otp_8270/1, otp_8273/1, otp_8340/1]).
@@ -47,6 +49,7 @@ all() ->
undefined ->
[start, compile, analyse, misc, stop,
distribution, reconnect, die_and_reconnect,
+ dont_reconnect_after_stop, stop_node_after_disconnect,
export_import, otp_5031, eif, otp_5305, otp_5418,
otp_6115, otp_7095, otp_8188, otp_8270, otp_8273,
otp_8340];
@@ -86,8 +89,11 @@ init_per_testcase(TC, Config) when TC =:= misc;
init_per_testcase(_TestCase, Config) ->
Config.
-end_per_testcase(_TestCase, _Config) ->
- %cover:stop(),
+end_per_testcase(TestCase, _Config) ->
+ case lists:member(TestCase,[start,compile,analyse,misc]) of
+ true -> ok;
+ false -> cover:stop()
+ end,
ok.
start(suite) -> [];
@@ -447,8 +453,8 @@ reconnect(Config) ->
%% Disconnect and check that node is removed from main cover node
net_kernel:disconnect(N1),
+ timer:sleep(500), % allow some to detect disconnect and for f:f2() call
[] = cover:which_nodes(),
- timer:sleep(500), % allow some time for the f:f2() call
%% Do some add one module (b) and remove one module (a)
code:purge(a),
@@ -520,6 +526,94 @@ die_and_reconnect(Config) ->
?t:stop_node(N1),
ok.
+%% Test that a stopped node is not marked as lost, i.e. that it is not
+%% reconnected if it is restarted (OTP-10638)
+dont_reconnect_after_stop(Config) ->
+ DataDir = ?config(data_dir, Config),
+ ok = file:set_cwd(DataDir),
+
+ {ok,f} = compile:file(f),
+
+ NodeName = cover_SUITE_dont_reconnect_after_stop,
+ {ok,N1} = ?t:start_node(NodeName,peer,
+ [{args," -pa " ++ DataDir},{start_cover,false}]),
+ {ok,f} = cover:compile(f),
+ {ok,[N1]} = cover:start(nodes()),
+
+ %% 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,[]),
+ [] = cover:which_nodes(),
+
+ check_f_calls(1,0),
+
+ %% Restart the node and check that cover does not reconnect
+ {ok,N1} = ?t:start_node(NodeName,peer,
+ [{args," -pa " ++ DataDir},{start_cover,false}]),
+ timer:sleep(300),
+ [] = cover:which_nodes(),
+ Beam = rpc:call(N1,code,which,[f]),
+ false = (Beam==cover_compiled),
+
+ %% One more call...
+ rpc:call(N1,f,f1,[]),
+ cover:flush(N1),
+
+ %% Ensure that the last call is not counted
+ check_f_calls(1,0),
+
+ cover:stop(),
+ ?t:stop_node(N1),
+ ok.
+
+%% Test that a node which is stopped while it is marked as lost is not
+%% reconnected if it is restarted (OTP-10638)
+stop_node_after_disconnect(Config) ->
+ DataDir = ?config(data_dir, Config),
+ ok = file:set_cwd(DataDir),
+
+ {ok,f} = compile:file(f),
+
+ NodeName = cover_SUITE_stop_node_after_disconnect,
+ {ok,N1} = ?t:start_node(NodeName,peer,
+ [{args," -pa " ++ DataDir},{start_cover,false}]),
+ {ok,f} = cover:compile(f),
+ {ok,[N1]} = cover:start(nodes()),
+
+ %% 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,[]),
+
+ check_f_calls(1,0),
+
+ %% Stop cover on node
+ cover:stop(N1),
+
+ %% Restart the node and check that cover does not reconnect
+ {ok,N1} = ?t:start_node(NodeName,peer,
+ [{args," -pa " ++ DataDir},{start_cover,false}]),
+ timer:sleep(300),
+ [] = cover:which_nodes(),
+ Beam = rpc:call(N1,code,which,[f]),
+ false = (Beam==cover_compiled),
+
+ %% One more call...
+ rpc:call(N1,f,f1,[]),
+ cover:flush(N1),
+
+ %% Ensure that the last call is not counted
+ check_f_calls(1,0),
+
+ cover:stop(),
+ ?t:stop_node(N1),
+ ok.
+
export_import(suite) -> [];
export_import(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
@@ -908,7 +1002,7 @@ otp_8270(Config) when is_list(Config) ->
ok.
otp_8273(doc) ->
- ["OTP-8270. Bug."];
+ ["OTP-8273. Bug."];
otp_8273(suite) -> [];
otp_8273(Config) when is_list(Config) ->
Test = <<"-module(t).
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index fd3e111d8d..cf49526156 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -2521,7 +2522,7 @@ otp_10192(doc) ->
otp_10192(Conf) when is_list(Conf) ->
PrivDir = ?privdir,
{ok, _Pid} = xref:start(s),
- Dir = filename:join(PrivDir, "�"),
+ Dir = filename:join(PrivDir, "ä"),
ok = file:make_dir(Dir),
{ok, []} = xref:add_directory(s, Dir),
xref:stop(s),
diff --git a/lib/wx/test/wx_basic_SUITE.erl b/lib/wx/test/wx_basic_SUITE.erl
index 20115a41fb..e240bbcfe8 100644
--- a/lib/wx/test/wx_basic_SUITE.erl
+++ b/lib/wx/test/wx_basic_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -128,7 +129,7 @@ wx_api(Config) ->
?m(true, wx:is_null(Wx)),
Null = ?mr(wx_ref, wx:null()),
?m(true, wx:is_null(Null)),
- Frame = ?mt(wxFrame, wxFrame:new(Wx, 1, "WX API: " ++ unicode:characters_to_list("������"))),
+ Frame = ?mt(wxFrame, wxFrame:new(Wx, 1, "WX API: " ++ unicode:characters_to_list("åäöÅÄÖ"))),
?m(false, wx:is_null(Frame)),
?m(wxFrame, wx:getObjectType(Frame)),
Env = ?mr(wx_env, wx:get_env()),
diff --git a/lib/xmerl/doc/src/motorcycles_dtd.txt b/lib/xmerl/doc/src/motorcycles_dtd.txt
index bab0d563f0..62ad4ac5fe 100644
--- a/lib/xmerl/doc/src/motorcycles_dtd.txt
+++ b/lib/xmerl/doc/src/motorcycles_dtd.txt
@@ -15,4 +15,5 @@
<!ELEMENT date (#PCDATA)>
<!ATTLIST bike year NMTOKEN #REQUIRED
color NMTOKENS #REQUIRED
- condition (useless | bad | serviceable | moderate | good | excellent | new | outstanding) "excellent" >
+ condition (useless | bad | serviceable | moderate | good |
+ excellent | new | outstanding) "excellent" >
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index 05431a5fd2..883153628c 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -461,7 +462,7 @@ hook(X, State) ->
event(_X, S) ->
S.
-%% The acc/3 function can return either {Acc�, S'} or {Acc', Pos', S'},
+%% The acc/3 function can return either {Acc´, S'} or {Acc', Pos', S'},
%% where Pos' can be derived from X#xmlElement.pos, X#xmlText.pos, or
%% X#xmlAttribute.pos (whichever is the current object type.)
%% The acc/3 function is not allowed to redefine the type of object
diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl
index 78d84d23a4..ffe227c671 100644
--- a/lib/xmerl/src/xmerl_xsd.erl
+++ b/lib/xmerl/src/xmerl_xsd.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -849,7 +850,7 @@ element_content({import,S=#xsd_state{schema_name=ThisSchema,
SchemaLocation = get_attribute_value(schemaLocation,I,absent),
%% If SchemaLocation is absent, the identification of that schema
%% is leaved to the instance, application or user, via the
- %% mechanisms described ��4.3 in XML Schema Part 1.
+ %% mechanisms described §4.3 in XML Schema Part 1.
S2 = process_external_schema_once(SchemaLocation,Namespace,S),
{{import,[]},S2#xsd_state{schema_name=ThisSchema,
diff --git a/lib/xmerl/test/xmerl_SUITE.erl b/lib/xmerl/test/xmerl_SUITE.erl
index 55b6d1844c..e21355f877 100644
--- a/lib/xmerl/test/xmerl_SUITE.erl
+++ b/lib/xmerl/test/xmerl_SUITE.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -531,8 +532,8 @@ ticket_7430(Config) ->
{xmlElement,a,a,[],
{xmlNamespace,[],[]},
[],1,[],
- [{xmlText,[{a,1}],1,[],"�",text},
- {xmlText,[{a,1}],2,[],"\n�",text}],
+ [{xmlText,[{a,1}],1,[],"é",text},
+ {xmlText,[{a,1}],2,[],"\né",text}],
[],_,undeclared} ->
ok;
_ ->
diff --git a/make/otp.mk.in b/make/otp.mk.in
index f2c2cee767..90f448d4a0 100644
--- a/make/otp.mk.in
+++ b/make/otp.mk.in
@@ -252,6 +252,7 @@ XSLTPROC = @XSLTPROC@
FOP = @FOP@
DOCGEN=$(ERL_TOP)/lib/erl_docgen
+FOP_CONFIG = $(DOCGEN)/priv/fop.xconf
ifneq (,$(findstring $(origin SPECS_ESRC),$(DUBIOUS_ORIGINS)))
SPECS_ESRC = ../../src
@@ -308,5 +309,5 @@ $(MAN9DIR)/%.9: %.xml
escript $(DOCGEN)/priv/bin/codeline_preprocessing.escript $< $@
.fo.pdf:
- $(FOP) -fo $< -pdf $@
+ $(FOP) -c $(FOP_CONFIG) -fo $< -pdf $@
diff --git a/system/doc/reference_manual/introduction.xml b/system/doc/reference_manual/introduction.xml
index 3dac5cfe13..7737c34469 100644
--- a/system/doc/reference_manual/introduction.xml
+++ b/system/doc/reference_manual/introduction.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2009</year>
+ <year>2003</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -150,6 +150,17 @@
</row>
<tcaption>Character Classes.</tcaption>
</table>
+ <p>In Erlang/OTP R16 the syntax of Erlang tokens was extended to
+ handle Unicode. To begin with the support is limited to strings,
+ but Erlang/OTP R18 is expected to handle Unicode atoms as well.
+ More about the usage of Unicode in Erlang source files can be
+ found in <seealso
+ marker="stdlib:unicode_usage#unicode_in_erlang">STDLIB's User'S
+ Guide</seealso>. The default encoding for Erlang source files
+ is still Latin-1, but in Erlang/OTP R17 the default encoding
+ will be UTF-8. The details on how to state the encoding of an
+ Erlang source file can be found in <seealso
+ marker="stdlib:epp#encoding">epp(3)</seealso>.</p>
</section>
</chapter>