summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/main.yaml2
-rw-r--r--OTP_VERSION2
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin6068 -> 6120 bytes
-rw-r--r--erts/config.h.in3
-rwxr-xr-xerts/configure48
-rw-r--r--erts/configure.ac36
-rw-r--r--erts/doc/src/notes.xml154
-rw-r--r--erts/emulator/Makefile.in2
-rw-r--r--erts/emulator/beam/beam_file.c2
-rw-r--r--erts/emulator/beam/bif.c1
-rw-r--r--erts/emulator/beam/code_ix.c8
-rw-r--r--erts/emulator/beam/dist.c19
-rw-r--r--erts/emulator/beam/emu/ops.tab5
-rw-r--r--erts/emulator/beam/erl_alloc.c2
-rw-r--r--erts/emulator/beam/erl_arith.c2
-rw-r--r--erts/emulator/beam/erl_async.c4
-rw-r--r--erts/emulator/beam/erl_bif_info.c7
-rw-r--r--erts/emulator/beam/erl_db.c2
-rw-r--r--erts/emulator/beam/erl_db_util.c107
-rw-r--r--erts/emulator/beam/erl_drv_thread.c6
-rw-r--r--erts/emulator/beam/erl_fun.h7
-rw-r--r--erts/emulator/beam/erl_map.c688
-rw-r--r--erts/emulator/beam/erl_map.h30
-rw-r--r--erts/emulator/beam/erl_md5.c26
-rw-r--r--erts/emulator/beam/erl_monitor_link.c22
-rw-r--r--erts/emulator/beam/erl_nif.c4
-rw-r--r--erts/emulator/beam/erl_node_tables.c14
-rw-r--r--erts/emulator/beam/erl_node_tables.h8
-rw-r--r--erts/emulator/beam/erl_posix_str.c3
-rw-r--r--erts/emulator/beam/erl_printf_term.c67
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c1
-rw-r--r--erts/emulator/beam/erl_process.c16
-rw-r--r--erts/emulator/beam/erl_process_lock.h3
-rw-r--r--erts/emulator/beam/erl_term.h7
-rw-r--r--erts/emulator/beam/erl_term_hashing.c67
-rw-r--r--erts/emulator/beam/erl_term_hashing.h8
-rw-r--r--erts/emulator/beam/erl_threads.h8
-rw-r--r--erts/emulator/beam/erl_trace.c8
-rw-r--r--erts/emulator/beam/erl_vm.h2
-rw-r--r--erts/emulator/beam/external.c49
-rw-r--r--erts/emulator/beam/hash.c3
-rw-r--r--erts/emulator/beam/io.c5
-rw-r--r--erts/emulator/beam/jit/arm/instr_map.cpp86
-rw-r--r--erts/emulator/beam/jit/arm/ops.tab4
-rw-r--r--erts/emulator/beam/jit/beam_jit_common.cpp3
-rw-r--r--erts/emulator/beam/jit/beam_jit_main.cpp6
-rw-r--r--erts/emulator/beam/jit/beam_jit_metadata.cpp2
-rw-r--r--erts/emulator/beam/jit/x86/instr_map.cpp92
-rw-r--r--erts/emulator/beam/jit/x86/ops.tab5
-rw-r--r--erts/emulator/beam/packet_parser.c4
-rw-r--r--erts/emulator/beam/utils.c33
-rw-r--r--erts/emulator/drivers/common/inet_drv.c10
-rw-r--r--erts/emulator/internal_doc/BeamAsm.md5
-rw-r--r--erts/emulator/nifs/common/prim_socket_int.h1
-rw-r--r--erts/emulator/nifs/common/prim_socket_nif.c14
-rw-r--r--erts/emulator/nifs/common/socket_int.h1
-rw-r--r--erts/emulator/nifs/common/socket_util.c14
-rw-r--r--erts/emulator/nifs/common/socket_util.h5
-rw-r--r--erts/emulator/nifs/unix/unix_socket_syncio.c3
-rw-r--r--erts/emulator/nifs/win32/win_socket_asyncio.c1990
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h2
-rw-r--r--erts/emulator/sys/unix/sys.c4
-rw-r--r--erts/emulator/sys/unix/sys_env.c10
-rw-r--r--erts/emulator/test/bs_utf_SUITE.erl4
-rw-r--r--erts/emulator/test/decode_packet_SUITE.erl2
-rw-r--r--erts/emulator/test/distribution_SUITE.erl127
-rw-r--r--erts/emulator/test/map_SUITE.erl74
-rw-r--r--erts/emulator/test/process_SUITE.erl50
-rwxr-xr-xerts/emulator/utils/make_driver_tab2
-rw-r--r--erts/epmd/src/epmd_srv.c7
-rw-r--r--erts/etc/common/escript.c2
-rw-r--r--erts/etc/common/heart.c22
-rw-r--r--erts/include/internal/ethread.h3
-rw-r--r--erts/lib_src/pthread/ethread.c24
-rw-r--r--erts/preloaded/ebin/prim_socket.beambin36524 -> 36556 bytes
-rw-r--r--erts/preloaded/src/prim_socket.erl12
-rw-r--r--erts/test/ethread_SUITE.erl12
-rw-r--r--erts/test/ethread_SUITE_data/ethread_tests.c121
-rw-r--r--erts/test/otp_SUITE.erl2
-rw-r--r--erts/vsn.mk2
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c2
-rw-r--r--lib/asn1/test/error_SUITE.erl2
-rw-r--r--lib/common_test/src/ct_run.erl2
-rw-r--r--lib/compiler/Makefile1
-rw-r--r--lib/compiler/doc/src/notes.xml37
-rw-r--r--lib/compiler/src/.gitignore1
-rw-r--r--lib/compiler/src/Makefile2
-rw-r--r--lib/compiler/src/beam_bounds.erl23
-rw-r--r--lib/compiler/src/beam_call_types.erl32
-rw-r--r--lib/compiler/src/beam_disasm.erl2
-rw-r--r--lib/compiler/src/beam_jump.erl1
-rw-r--r--lib/compiler/src/beam_ssa.erl15
-rw-r--r--lib/compiler/src/beam_ssa_alias.erl15
-rw-r--r--lib/compiler/src/beam_ssa_check.erl5
-rw-r--r--lib/compiler/src/beam_ssa_codegen.erl6
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl2
-rw-r--r--lib/compiler/src/beam_ssa_private_append.erl23
-rw-r--r--lib/compiler/src/beam_types.erl25
-rw-r--r--lib/compiler/src/beam_validator.erl22
-rw-r--r--lib/compiler/test/beam_bounds_SUITE.erl6
-rw-r--r--lib/compiler/test/beam_jump_SUITE.erl8
-rw-r--r--lib/compiler/test/beam_ssa_SUITE.erl105
-rw-r--r--lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl27
-rw-r--r--lib/compiler/test/beam_ssa_check_SUITE_data/sanity_checks.erl16
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl81
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl21
-rw-r--r--lib/compiler/test/bif_SUITE.erl45
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl27
-rw-r--r--lib/compiler/test/compile_SUITE.erl2
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/crypto/c_src/dh.c6
-rw-r--r--lib/crypto/c_src/openssl_config.h9
-rw-r--r--lib/crypto/doc/src/new_api.xml2
-rw-r--r--lib/crypto/doc/src/notes.xml16
-rw-r--r--lib/crypto/src/crypto.erl2
-rw-r--r--lib/crypto/test/crypto_SUITE.erl25
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml32
-rw-r--r--lib/dialyzer/src/dialyzer.app.src2
-rw-r--r--lib/dialyzer/src/dialyzer.erl4
-rw-r--r--lib/dialyzer/src/dialyzer.hrl5
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl9
-rw-r--r--lib/dialyzer/src/dialyzer_cl_parse.erl849
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl23
-rw-r--r--lib/dialyzer/src/dialyzer_options.erl101
-rw-r--r--lib/dialyzer/src/typer.erl18
-rw-r--r--lib/dialyzer/test/incremental_SUITE.erl176
-rw-r--r--lib/dialyzer/test/incremental_SUITE_data/extra_modules/ebin/.gitignore5
-rw-r--r--lib/dialyzer/test/incremental_SUITE_data/extra_modules/src/extra_module.erl14
-rw-r--r--lib/dialyzer/test/incremental_SUITE_data/extra_modules/src/extra_modules.app.src8
-rw-r--r--lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl4
-rw-r--r--lib/dialyzer/test/map_SUITE_data/src/map_galore.erl4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/bs_segments3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/gh_71533
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bs_segments.erl7
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/gh_7153.erl5
-rw-r--r--lib/diameter/src/diameter.appup.src8
-rw-r--r--lib/diameter/src/info/diameter_dbg.erl2
-rw-r--r--lib/diameter/test/diameter_config_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_tls_SUITE.erl2
-rw-r--r--lib/edoc/test/edoc_SUITE.erl15
-rw-r--r--lib/edoc/test/edoc_SUITE_data/module_with_feature.erl2
-rw-r--r--lib/eldap/doc/src/eldap.xml2
-rw-r--r--lib/eldap/doc/src/notes.xml16
-rw-r--r--lib/eldap/vsn.mk2
-rwxr-xr-xlib/erl_interface/configure6
-rw-r--r--lib/erl_interface/configure.ac2
-rw-r--r--lib/erl_interface/doc/src/ei_users_guide.xml14
-rw-r--r--lib/erl_interface/doc/src/notes.xml16
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c4
-rw-r--r--lib/erl_interface/src/prog/erl_call.c8
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/et_intro.xml2
-rw-r--r--lib/et/src/et_collector.erl2
-rw-r--r--lib/ftp/test/ftp_SUITE.erl2
-rw-r--r--lib/inets/doc/src/http_uri.xml2
-rw-r--r--lib/inets/doc/src/httpd_util.xml2
-rw-r--r--lib/inets/doc/src/notes.xml46
-rw-r--r--lib/inets/examples/server_root/Makefile2
-rw-r--r--lib/inets/examples/server_root/conf/httpd.conf2
-rw-r--r--lib/inets/src/http_client/httpc.erl4
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl77
-rw-r--r--lib/inets/src/http_lib/http_uri.erl2
-rw-r--r--lib/inets/test/http_test_lib.erl1
-rw-r--r--lib/inets/test/httpc_SUITE.erl191
-rw-r--r--lib/inets/test/httpd_SUITE.erl2
-rw-r--r--lib/inets/test/inets_test_lib.erl1
-rw-r--r--lib/inets/test/make_certs.erl1
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/jinterface/doc/src/jinterface_users_guide.xml2
-rw-r--r--lib/kernel/Makefile2
-rw-r--r--lib/kernel/doc/src/application.xml2
-rw-r--r--lib/kernel/doc/src/code.xml2
-rw-r--r--lib/kernel/doc/src/disk_log.xml4
-rw-r--r--lib/kernel/doc/src/erpc.xml2
-rw-r--r--lib/kernel/doc/src/rpc.xml2
-rw-r--r--lib/kernel/doc/src/socket.xml131
-rw-r--r--lib/kernel/doc/src/socket_usage.xml2
-rw-r--r--lib/kernel/src/disk_log.erl2
-rw-r--r--lib/kernel/src/disk_log.hrl2
-rw-r--r--lib/kernel/src/disk_log_1.erl2
-rw-r--r--lib/kernel/src/gen_tcp_socket.erl16
-rw-r--r--lib/kernel/src/inet_db.erl5
-rw-r--r--lib/kernel/src/inet_parse.erl13
-rw-r--r--lib/kernel/src/inet_res.erl9
-rw-r--r--lib/kernel/src/net_kernel.erl2
-rw-r--r--lib/kernel/src/seq_trace.erl2
-rw-r--r--lib/kernel/src/socket.erl10
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl2
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl13
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl33
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl39
-rw-r--r--lib/kernel/test/inet_SUITE.erl18
-rw-r--r--lib/kernel/test/logger_disk_log_h_SUITE.erl22
-rw-r--r--lib/kernel/test/logger_std_h_SUITE.erl2
-rw-r--r--lib/kernel/test/logger_stress_SUITE.erl2
-rw-r--r--lib/kernel/test/socket_SUITE.erl224
-rw-r--r--lib/kernel/test/socket_test_evaluator.erl2
-rw-r--r--lib/kernel/test/socket_test_lib.erl2
-rw-r--r--lib/kernel/test/socket_test_ttest_tcp_socket.erl2
-rw-r--r--lib/megaco/configure.ac2
-rw-r--r--lib/megaco/doc/src/megaco_intro.xml2
-rw-r--r--lib/observer/doc/src/observer.xml8
-rw-r--r--lib/observer/src/observer_wx.erl4
-rw-r--r--lib/observer/src/ttb.erl6
-rw-r--r--lib/odbc/c_src/odbcserver.c2
-rw-r--r--lib/odbc/configure.ac2
-rw-r--r--lib/os_mon/c_src/cpu_sup.c90
-rw-r--r--lib/os_mon/doc/src/cpu_sup.xml2
-rw-r--r--lib/os_mon/doc/src/notes.xml17
-rw-r--r--lib/os_mon/src/cpu_sup.erl5
-rw-r--r--lib/os_mon/src/memsup.erl2
-rw-r--r--lib/os_mon/test/cpu_sup_SUITE.erl2
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/reltool/doc/src/reltool_intro.xml2
-rw-r--r--lib/runtime_tools/doc/src/part.xml2
-rw-r--r--lib/runtime_tools/src/dbg.erl7
-rw-r--r--lib/runtime_tools/src/erts_alloc_config.erl2
-rw-r--r--lib/runtime_tools/test/dbg_SUITE.erl40
-rw-r--r--lib/snmp/doc/src/notes.xml18
-rw-r--r--lib/snmp/doc/src/snmp_intro.xml2
-rw-r--r--lib/snmp/vsn.mk2
-rw-r--r--lib/ssh/src/ssh_dbg.erl2
-rw-r--r--lib/ssl/doc/src/notes.xml41
-rw-r--r--lib/ssl/doc/src/ssl.xml2
-rw-r--r--lib/ssl/src/dtls_connection.erl9
-rw-r--r--lib/ssl/src/dtls_handshake.hrl2
-rw-r--r--lib/ssl/src/dtls_v1.erl2
-rw-r--r--lib/ssl/src/ssl.erl10
-rw-r--r--lib/ssl/src/ssl_cipher.erl4
-rw-r--r--lib/ssl/src/ssl_internal.hrl2
-rw-r--r--lib/ssl/src/ssl_logger.erl2
-rw-r--r--lib/ssl/src/ssl_record.erl2
-rw-r--r--lib/ssl/src/ssl_record.hrl2
-rw-r--r--lib/ssl/src/ssl_session.erl2
-rw-r--r--lib/ssl/src/tls_record.erl2
-rw-r--r--lib/ssl/src/tls_record.hrl2
-rw-r--r--lib/ssl/src/tls_record_1_3.erl2
-rw-r--r--lib/ssl/src/tls_record_1_3.hrl2
-rw-r--r--lib/ssl/src/tls_socket.erl2
-rw-r--r--lib/ssl/test/openssl_alpn_SUITE.erl4
-rw-r--r--lib/ssl/test/openssl_renegotiate_SUITE.erl2
-rw-r--r--lib/ssl/test/openssl_server_cert_SUITE.erl2
-rw-r--r--lib/ssl/test/property_test/ssl_eqc_handshake.erl2
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_api_SUITE.erl8
-rw-r--r--lib/ssl/test/ssl_cipher_SUITE.erl11
-rw-r--r--lib/ssl/test/ssl_dist_test_lib.erl2
-rw-r--r--lib/ssl/test/ssl_mfl_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_reject_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_renegotiate_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_session_SUITE.erl24
-rw-r--r--lib/ssl/test/ssl_test_lib.erl26
-rw-r--r--lib/ssl/test/tls_1_3_record_SUITE.erl2
-rw-r--r--lib/ssl/test/tls_1_3_version_SUITE.erl2
-rw-r--r--lib/ssl/test/tls_server_session_ticket_SUITE.erl2
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/Makefile1
-rw-r--r--lib/stdlib/doc/src/Makefile1
-rw-r--r--lib/stdlib/doc/src/argparse.xml739
-rw-r--r--lib/stdlib/doc/src/gb_sets.xml46
-rw-r--r--lib/stdlib/doc/src/gen_event.xml2
-rw-r--r--lib/stdlib/doc/src/notes.xml16
-rw-r--r--lib/stdlib/doc/src/orddict.xml2
-rw-r--r--lib/stdlib/doc/src/ordsets.xml5
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml4
-rw-r--r--lib/stdlib/doc/src/queue.xml2
-rw-r--r--lib/stdlib/doc/src/ref_man.xml1
-rw-r--r--lib/stdlib/doc/src/sets.xml65
-rw-r--r--lib/stdlib/doc/src/specs.xml1
-rw-r--r--lib/stdlib/src/Makefile1
-rw-r--r--lib/stdlib/src/argparse.erl1357
-rw-r--r--lib/stdlib/src/erl_lint.erl52
-rw-r--r--lib/stdlib/src/otp_internal.erl2
-rw-r--r--lib/stdlib/src/rand.erl2
-rw-r--r--lib/stdlib/src/sets.erl17
-rw-r--r--lib/stdlib/src/stdlib.app.src3
-rw-r--r--lib/stdlib/src/stdlib.appup.src8
-rw-r--r--lib/stdlib/test/Makefile1
-rw-r--r--lib/stdlib/test/argparse_SUITE.erl1063
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl168
-rw-r--r--lib/stdlib/test/gen_statem_SUITE.erl2
-rw-r--r--lib/stdlib/test/property_test/uri_string_recompose.erl2
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl8
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/src/epp_dodger.erl2
-rw-r--r--lib/tools/src/lcnt.erl8
-rw-r--r--lib/tools/src/xref_reader.erl2
-rw-r--r--lib/wx/api_gen/gl_gen.erl7
-rw-r--r--lib/wx/api_gen/gl_gen_erl.erl12
-rw-r--r--lib/wx/api_gen/gl_gen_nif.erl35
-rw-r--r--lib/wx/api_gen/glapi.conf16
-rw-r--r--lib/wx/api_gen/wx_extra/added_func.h6
-rw-r--r--lib/wx/api_gen/wx_gen_nif.erl6
-rw-r--r--lib/wx/api_gen/wxapi.conf21
-rw-r--r--lib/wx/c_src/egl_impl.c19
-rw-r--r--lib/wx/c_src/gen/gl_nif.cpp18
-rw-r--r--lib/wx/c_src/gen/wxe_func_table.cpp2772
-rw-r--r--lib/wx/c_src/gen/wxe_init.cpp8
-rw-r--r--lib/wx/c_src/gen/wxe_macros.h5
-rw-r--r--lib/wx/c_src/gen/wxe_wrapper_3.cpp63
-rw-r--r--lib/wx/c_src/wxe_gl.cpp41
-rw-r--r--lib/wx/c_src/wxe_gl.h4
-rw-r--r--lib/wx/c_src/wxe_impl.cpp35
-rw-r--r--lib/wx/c_src/wxe_impl.h5
-rw-r--r--lib/wx/c_src/wxe_nif.c12
-rw-r--r--lib/wx/c_src/wxe_return.cpp9
-rw-r--r--lib/wx/configure.ac2
-rw-r--r--lib/wx/doc/src/gl.xml13
-rw-r--r--lib/wx/doc/src/notes.xml16
-rw-r--r--lib/wx/doc/src/wxGLCanvas.xml17
-rw-r--r--lib/wx/doc/src/wxGLContext.xml13
-rw-r--r--lib/wx/include/wx.hrl4
-rw-r--r--lib/wx/src/gen/gl.erl22
-rw-r--r--lib/wx/src/gen/wxGLCanvas.erl21
-rw-r--r--lib/wx/src/gen/wxGLContext.erl12
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl2269
-rw-r--r--lib/wx/src/wxe_master.erl7
-rw-r--r--lib/wx/src/wxe_util.erl8
-rw-r--r--lib/wx/test/wx_class_SUITE.erl13
-rw-r--r--lib/wx/test/wx_opengl_SUITE.erl75
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--make/app_targets.mk2
-rw-r--r--make/autoconf/otp.m46
-rw-r--r--otp_versions.table3
-rw-r--r--system/doc/general_info/DEPRECATIONS1
-rw-r--r--system/doc/reference_manual/expressions.xml15
327 files changed, 11472 insertions, 5265 deletions
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index f0a12221b0..ddb0b20361 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -238,7 +238,7 @@ jobs:
shell: cmd
run: |
choco install openssl
- move "c:\\Program Files\\OpenSSL-Win64" "c:\\OpenSSL-Win64"
+ move "c:\\Program Files\\OpenSSL" "c:\\OpenSSL-Win64"
- name: Cache wxWidgets
uses: actions/cache@v3
diff --git a/OTP_VERSION b/OTP_VERSION
index bbb81b34fd..afd1a8c459 100644
--- a/OTP_VERSION
+++ b/OTP_VERSION
@@ -1 +1 @@
-26.0-rc2
+26.0-rc3
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index b7a34e9bdd..4009644828 100644
--- a/bootstrap/lib/stdlib/ebin/otp_internal.beam
+++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam
Binary files differ
diff --git a/erts/config.h.in b/erts/config.h.in
index ee9390f1b9..d7fecf8631 100644
--- a/erts/config.h.in
+++ b/erts/config.h.in
@@ -89,6 +89,9 @@
/* Socket address dl length */
#undef ESOCK_SDL_LEN
+/* Use extended error info */
+#undef ESOCK_USE_EXTENDED_ERROR_INFO
+
/* Interface hwaddr supported */
#undef ESOCK_USE_HWADDR
diff --git a/erts/configure b/erts/configure
index 2c76bc1587..a09c84ff09 100755
--- a/erts/configure
+++ b/erts/configure
@@ -860,6 +860,7 @@ with_threadnames
enable_builtin_zlib
enable_esock
enable_esock_use_rcvsndtimeo
+enable_esock_extended_error_info
with_esock_counter_size
enable_esock_socket_registry
with_clock_resolution
@@ -1596,6 +1597,10 @@ Optional Features:
--disable-esock-rcvsndtimeo
disable use of the option(s) rcvtimeo and sndtimeo
(default)
+ --enable-esock-extended-error-info
+ enable use of extended error info
+ --disable-esock-extended-error-info
+ disable use of extended error info (default)
--enable-esock-socket-registry
enable use of the socket registry by default
(default)
@@ -14193,7 +14198,7 @@ int
main (void)
{
- __asm__ __volatile__("isb sy" : : : "memory");
+ __asm__ __volatile__("isb sy\n" : : : "memory");
;
return 0;
@@ -14227,7 +14232,7 @@ int
main (void)
{
- char data[512]; __asm__ __volatile__("dc cvau, %0" : "r" (data) : : "memory");
+ char data[512]; __asm__ __volatile__("dc cvau, %0\n" :: "r" (data) : "memory");
;
return 0;
@@ -14261,7 +14266,7 @@ int
main (void)
{
- char data[512]; __asm__ __volatile__("ic ivau, %0" : "r" (data) : : "memory");
+ char data[512]; __asm__ __volatile__("ic ivau, %0\n" :: "r" (data) : "memory");
;
return 0;
@@ -16070,6 +16075,21 @@ fi
+# Check whether --enable-esock_extended_error_info was given.
+if test ${enable_esock_extended_error_info+y}
+then :
+ enableval=$enable_esock_extended_error_info;
+fi
+
+
+if test "x$enable_esock_extended_error_info" != "xno"; then
+
+printf "%s\n" "#define ESOCK_USE_EXTENDED_ERROR_INFO 1" >>confdefs.h
+
+fi
+
+
+
# Check whether --with-esock-counter-size was given.
if test ${with_esock_counter_size+y}
@@ -24539,7 +24559,27 @@ then :
JIT_ARCH=x86
;;
arm64)
- JIT_ARCH=arm
+ case "$OPSYS" in
+ win32|darwin)
+ # These platforms have dedicated system calls for clearing
+ # instruction cache, and don't require us to manually issue
+ # instruction barriers on all threads.
+ JIT_ARCH=arm
+ ;;
+ *)
+ # We need to use `DC CVAU`, `IC IVAU`, and `ISB SY` to clear
+ # instruction cache. These have already been tested as part of
+ # ETHR_CHK_GCC_ATOMIC_OPS([]).
+
+ if test "$ethr_arm_isb_sy_instr_val$ethr_arm_dc_cvau_instr_val$ethr_arm_ic_ivau_instr_val" = "111"; then
+ JIT_ARCH=arm
+ else
+ enable_jit=no
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: JIT disabled due to lack of cache-clearing instructions" >&5
+printf "%s\n" "$as_me: WARNING: JIT disabled due to lack of cache-clearing instructions" >&2;}
+ fi
+ ;;
+ esac
;;
*)
if test ${enable_jit} = yes; then
diff --git a/erts/configure.ac b/erts/configure.ac
index bedaff3c0b..540cc4b3cb 100644
--- a/erts/configure.ac
+++ b/erts/configure.ac
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-Autoconf-*
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1997-2022. All Rights Reserved.
+dnl Copyright Ericsson AB 1997-2023. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
@@ -1356,6 +1356,19 @@ if test "x$enable_esock_rcvsndtimeo" = "xyes"; then
fi
+dnl *** ESOCK_USE_EXTERNDED_ERROR_INFO ***
+
+AC_ARG_ENABLE(esock_extended_error_info,
+AS_HELP_STRING([--enable-esock-extended-error-info], [enable use of extended error info])
+AS_HELP_STRING([--disable-esock-extended-error-info], [disable use of extended error info (default)]))
+
+dnl Temporary! Currently we require eei to be *explicitly*
+dnl disabled (for debug reasons).
+if test "x$enable_esock_extended_error_info" != "xno"; then
+ AC_DEFINE(ESOCK_USE_EXTENDED_ERROR_INFO, [1], [Use extended error info])
+fi
+
+
dnl *** ESOCK_COUNTER_SIZE ***
AC_ARG_WITH(esock-counter-size,
@@ -2855,7 +2868,26 @@ AS_IF([test ${enable_jit} != no],
JIT_ARCH=x86
;;
arm64)
- JIT_ARCH=arm
+ case "$OPSYS" in
+ win32|darwin)
+ # These platforms have dedicated system calls for clearing
+ # instruction cache, and don't require us to manually issue
+ # instruction barriers on all threads.
+ JIT_ARCH=arm
+ ;;
+ *)
+ # We need to use `DC CVAU`, `IC IVAU`, and `ISB SY` to clear
+ # instruction cache. These have already been tested as part of
+ # ETHR_CHK_GCC_ATOMIC_OPS([]).
+
+ if test "$ethr_arm_isb_sy_instr_val$ethr_arm_dc_cvau_instr_val$ethr_arm_ic_ivau_instr_val" = "111"; then
+ JIT_ARCH=arm
+ else
+ enable_jit=no
+ AC_MSG_WARN([JIT disabled due to lack of cache-clearing instructions])
+ fi
+ ;;
+ esac
;;
*)
if test ${enable_jit} = yes; then
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index f39f020c16..1f372823e8 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -31,6 +31,102 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 13.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If a runtime system which was starting the distribution
+ already had existing pids, ports, or references referring
+ to a node with the same nodename/creation pair that the
+ runtime system was about to use, these already existing
+ pids, ports, or references would not work as expected in
+ various situations after the node had gone alive. This
+ could only occur if the runtime system was communicated
+ such pids, ports, or references prior to the distribution
+ was started. That is, it was extremely unlikely to happen
+ unless the distribution was started dynamically and was
+ even then very unlikely to happen. The runtime system now
+ checks for already existing pids, ports, and references
+ with the same nodename/creation pair that it is about to
+ use. If such are found another creation will be chosen in
+ order to avoid these issues.</p>
+ <p>
+ Own Id: OTP-18570 Aux Id: PR-7190 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug in the loader that prevented certain
+ modules compiled with <c>no_ssa_opt</c> from being
+ loaded.</p>
+ <p>
+ Own Id: OTP-18519 Aux Id: GH-7024 </p>
+ </item>
+ <item>
+ <p>
+ Implementations of the <seecref
+ marker="erts:driver_entry#call"><c>call()</c></seecref>
+ driver callback that returned a faulty encoded result
+ could cause a memory leak and could cause invalid data on
+ the heap of the processes calling <seemfa
+ marker="erts:erlang#port_call/3"><c>erlang:port_call/3</c></seemfa>.</p>
+ <p>
+ Own Id: OTP-18525 Aux Id: PR-7049 </p>
+ </item>
+ <item>
+ <p>Fixed a memory corruption issue when upgrading code.
+ The bug was introduced in <c>OTP 25.3</c></p>
+ <p>
+ Own Id: OTP-18553</p>
+ </item>
+ <item>
+ <p>Fixed configure tests for a few ARM-specific
+ instructions, which prevented the emulator from being
+ built on some platforms.</p>
+ <p>
+ Own Id: OTP-18554</p>
+ </item>
+ <item>
+ <p>
+ Aliases created in combination with a monitor using the
+ <c>{alias, explicit_unalias}</c> option stopped working
+ from remote nodes when a <c>'DOWN'</c> signal had been
+ received due to the monitor or if the monitor was removed
+ using the <c>erlang:demonitor()</c> BIF.</p>
+ <p>
+ This bug was introduced in OTP 24.3.4.10 and OTP 25.3.</p>
+ <p>
+ Own Id: OTP-18557 Aux Id: PR-7131, OTP-18496 </p>
+ </item>
+ <item>
+ <p>In rare circumstances, bit syntax matching of an
+ invalid code point for a <c>utf32</c> would crash the
+ runtime system.</p>
+ <p>
+ Own Id: OTP-18560</p>
+ </item>
+ <item>
+ <p>
+ Building the runtime system failed when native atomic
+ support was missing. Note that execution on such systems
+ have only been rudimentary tested.</p>
+ <p>
+ Own Id: OTP-18563 Aux Id: GH-7114, PR-7159 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 13.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1392,6 +1488,64 @@
</section>
+<section><title>Erts 12.3.2.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug sometimes causing emulator crash at node shutdown
+ when there are pending connections. Only seen when
+ running duel distribution protocols, inet_drv and
+ inet_tls_dist.</p>
+ <p>
+ Own Id: OTP-18243 Aux Id: GH-6247, PR-6258 </p>
+ </item>
+ <item>
+ <p>Fix bug in <c>binary_to_term</c> (and distributed
+ receive) when decoding a large map (&gt;32 keys) with
+ unsorted small maps (&lt;= 32) as keys of the large
+ map.</p>
+ <p>This was only a problem if the term was encoded by
+ <c>erl_interface</c>, <c>jinterface</c> or otherwise, as
+ the VM itself always encodes small maps with sorted
+ keys.</p>
+ <p>The "binary_to_term" would appear as successful but
+ the created large map was internally inconsistent. The
+ smaller key-maps could not be found with maps:get and
+ friends. Other operations such as map compare and merge
+ could probably also give incorrect results.</p>
+ <p>
+ Own Id: OTP-18343 Aux Id: GH-6496 </p>
+ </item>
+ <item>
+ <p>
+ Implementations of the <seecref
+ marker="erts:driver_entry#call"><c>call()</c></seecref>
+ driver callback that returned a faulty encoded result
+ could cause a memory leak and could cause invalid data on
+ the heap of the processes calling <seemfa
+ marker="erts:erlang#port_call/3"><c>erlang:port_call/3</c></seemfa>.</p>
+ <p>
+ Own Id: OTP-18525 Aux Id: PR-7049 </p>
+ </item>
+ <item>
+ <p>
+ Aliases created in combination with a monitor using the
+ <c>{alias, explicit_unalias}</c> option stopped working
+ from remote nodes when a <c>'DOWN'</c> signal had been
+ received due to the monitor or if the monitor was removed
+ using the <c>erlang:demonitor()</c> BIF.</p>
+ <p>
+ This bug was introduced in OTP 24.3.4.10 and OTP 25.3.</p>
+ <p>
+ Own Id: OTP-18557 Aux Id: PR-7131, OTP-18496 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 12.3.2.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index d911febb81..5451bdf804 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2022. All Rights Reserved.
+# Copyright Ericsson AB 1996-2023. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/erts/emulator/beam/beam_file.c b/erts/emulator/beam/beam_file.c
index e1215e8640..d210d0fc16 100644
--- a/erts/emulator/beam/beam_file.c
+++ b/erts/emulator/beam/beam_file.c
@@ -1318,7 +1318,7 @@ int iff_read_chunk(IFF_File *iff, Uint id, IFF_Chunk *chunk)
return read_beam_chunks(iff, 1, &id, chunk);
}
-void beamfile_init() {
+void beamfile_init(void) {
Eterm suffix;
Eterm *hp;
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 9ab1be5b90..80eb260153 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -374,6 +374,7 @@ demonitor(Process *c_p, Eterm ref, Eterm *multip)
NIL,
THE_NON_VALUE);
amdp->origin.flags = mon->flags & ERTS_ML_STATE_ALIAS_MASK;
+ mon->flags &= ~ERTS_ML_STATE_ALIAS_MASK;
erts_monitor_tree_replace(&ERTS_P_MONITORS(c_p), mon, &amdp->origin);
break;
}
diff --git a/erts/emulator/beam/code_ix.c b/erts/emulator/beam/code_ix.c
index e2e275442e..3888c72363 100644
--- a/erts/emulator/beam/code_ix.c
+++ b/erts/emulator/beam/code_ix.c
@@ -276,7 +276,7 @@ int erts_try_seize_code_stage_permission(Process* c_p)
return try_seize_code_permission(&code_stage_permission, c_p, NULL, NULL);
}
-void erts_release_code_stage_permission() {
+void erts_release_code_stage_permission(void) {
release_code_permission(&code_stage_permission);
}
@@ -304,7 +304,7 @@ int erts_try_seize_code_load_permission(Process* c_p) {
return 0;
}
-void erts_release_code_load_permission() {
+void erts_release_code_load_permission(void) {
erts_release_code_mod_permission();
erts_release_code_stage_permission();
}
@@ -474,7 +474,7 @@ static void schedule_blocking_code_barriers(void *ignored) {
}
#endif
-void erts_blocking_code_barrier()
+void erts_blocking_code_barrier(void)
{
#ifdef DEBUG
erts_debug_unrequire_code_barrier();
@@ -487,7 +487,7 @@ void erts_blocking_code_barrier()
#endif
}
-void erts_code_ix_finalize_wait() {
+void erts_code_ix_finalize_wait(void) {
#ifdef CODE_IX_ISSUE_INSTRUCTION_BARRIERS
if (erts_atomic32_read_nob(&outstanding_blocking_code_barriers) != 0) {
ERTS_THR_INSTRUCTION_BARRIER;
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index ca6aa40185..158f7116a2 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -4884,8 +4884,21 @@ BIF_RETTYPE setnode_2(BIF_ALIST_2)
erts_thr_progress_block();
success = (!ERTS_PROC_IS_EXITING(net_kernel)
- & !ERTS_PROC_GET_DIST_ENTRY(net_kernel));
+ && !ERTS_PROC_GET_DIST_ENTRY(net_kernel));
if (success) {
+ /*
+ * Ensure we don't use a nodename-creation pair with
+ * external identifiers existing in the system.
+ */
+ while (!0) {
+ ErlNode *nep;
+ if (creation < 4)
+ creation = 4;
+ nep = erts_find_node(BIF_ARG_1, creation);
+ if (!nep || erts_node_refc(nep) == 0)
+ break;
+ creation++;
+ }
inc_no_nodes();
erts_set_this_node(BIF_ARG_1, (Uint32) creation);
erts_this_dist_entry->creation = creation;
@@ -5898,10 +5911,10 @@ BIF_RETTYPE erts_internal_dist_spawn_request_4(BIF_ALIST_4)
ok_result = ref;
else {
Eterm *hp = HAlloc(BIF_P, 3);
- Eterm bool = ((monitor_oflags & ERTS_ML_FLG_SPAWN_MONITOR)
+ Eterm spawns_monitor = ((monitor_oflags & ERTS_ML_FLG_SPAWN_MONITOR)
? am_true : am_false);
ASSERT(BIF_ARG_4 == am_spawn_opt);
- ok_result = TUPLE2(hp, ref, bool);
+ ok_result = TUPLE2(hp, ref, spawns_monitor);
}
code = erts_dsig_prepare(&ctx, dep,
diff --git a/erts/emulator/beam/emu/ops.tab b/erts/emulator/beam/emu/ops.tab
index 220115cc8a..7c4447d145 100644
--- a/erts/emulator/beam/emu/ops.tab
+++ b/erts/emulator/beam/emu/ops.tab
@@ -1296,6 +1296,11 @@ bs_skip_utf16 Fail=f Ms=xy Unit=u Flags=u => bs_get_utf16 Fail Ms Unit Flags x
i_bs_get_utf16 xy f? t d
+bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst | equal(Ms, Dst) =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags x |
+ i_bs_validate_unicode_retract Fail x Ms |
+ move x Dst
+
bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst=d =>
bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst |
i_bs_validate_unicode_retract Fail Dst Ms
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 6e81fafd45..a344b585ae 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c
index 813f79edaa..9815dd0a6c 100644
--- a/erts/emulator/beam/erl_arith.c
+++ b/erts/emulator/beam/erl_arith.c
@@ -1310,6 +1310,6 @@ Eterm erts_bnot(Process* p, Eterm arg)
}
/* Needed to remove compiler optimization */
-double erts_get_positive_zero_float() {
+double erts_get_positive_zero_float(void) {
return 0.0f;
}
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index 3e3dc3a29d..1dd6ef18f0 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -199,7 +199,7 @@ erts_init_async(void)
for (i = 0; i < erts_async_max_threads; i++) {
ErtsAsyncQ *aq = async_q(i);
- erts_snprintf(thr_opts.name, sizeof(thr_name), "async_%d", i+1);
+ erts_snprintf(thr_opts.name, sizeof(thr_name), "erts_async_%d", i+1);
erts_thr_create(&aq->thr_id, async_main, (void*) aq, &thr_opts);
}
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 8ba4a7a3ae..4ba368ec7c 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -4275,6 +4275,13 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
BIF_RET(am_ok);
}
#endif
+ else if (ERTS_IS_ATOM_STR("hashmap_collision_bonanza", BIF_ARG_1)) {
+#ifdef DBG_HASHMAP_COLLISION_BONANZA
+ return am_true;
+#else
+ return am_false;
+#endif
+ }
}
else if (is_tuple(BIF_ARG_1)) {
Eterm* tp = tuple_val(BIF_ARG_1);
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 076a407603..8f5e1a9543 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -5523,7 +5523,7 @@ erts_db_foreach_thr_prgr_offheap(void (*func)(ErlOffHeap *, void *),
/* retrieve max number of ets tables */
Uint
-erts_db_get_max_tabs()
+erts_db_get_max_tabs(void)
{
return db_max_tabs;
}
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 38d755f7f6..af5aa09a5c 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -947,8 +947,8 @@ static Eterm dmc_lookup_bif_reversed(void *f);
static int cmp_uint(void *a, void *b);
static int cmp_guard_bif(void *a, void *b);
static int match_compact(ErlHeapFragment *expr, DMCErrInfo *err_info);
-static Uint my_size_object(Eterm t);
-static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap);
+static Uint my_size_object(Eterm t, int is_hashmap_node);
+static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap, int);
/* Guard subroutines */
static void
@@ -4130,11 +4130,11 @@ static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(UWord) *text,
if (is_immed(t)) {
tmp = t;
} else {
- sz = my_size_object(t);
+ sz = my_size_object(t, 0);
if (sz) {
emb = new_message_buffer(sz);
hp = emb->mem;
- tmp = my_copy_struct(t,&hp,&(emb->off_heap));
+ tmp = my_copy_struct(t,&hp,&(emb->off_heap), 0);
emb->next = context->save;
context->save = emb;
}
@@ -5672,33 +5672,39 @@ static int match_compact(ErlHeapFragment *expr, DMCErrInfo *err_info)
/*
** Simple size object that takes care of function calls and constant tuples
*/
-static Uint my_size_object(Eterm t)
+static Uint my_size_object(Eterm t, int is_hashmap_node)
{
Uint sum = 0;
- Eterm tmp;
Eterm *p;
switch (t & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_LIST:
- sum += 2 + my_size_object(CAR(list_val(t))) +
- my_size_object(CDR(list_val(t)));
+ sum += 2 + my_size_object(CAR(list_val(t)), 0) +
+ my_size_object(CDR(list_val(t)), 0);
break;
case TAG_PRIMARY_BOXED:
if (is_tuple(t)) {
- if (tuple_val(t)[0] == make_arityval(1) && is_tuple(tmp = tuple_val(t)[1])) {
- Uint i,n;
- p = tuple_val(tmp);
- n = arityval(p[0]);
- sum += 1 + n;
- for (i = 1; i <= n; ++i)
- sum += my_size_object(p[i]);
- } else if (tuple_val(t)[0] == make_arityval(2) &&
- is_atom(tmp = tuple_val(t)[1]) &&
- tmp == am_const) {
+ Eterm* tpl = tuple_val(t);
+ Uint i,n;
+
+ if (is_hashmap_node) {
+ /* hashmap collision node, no matchspec syntax here */
+ }
+ else if (tpl[0] == make_arityval(1) && is_tuple(tpl[1])) {
+ tpl = tuple_val(tpl[1]);
+ }
+ else if (tpl[0] == make_arityval(2) && tpl[1] == am_const) {
sum += size_object(tuple_val(t)[2]);
- } else {
+ break;
+ }
+ else {
erts_exit(ERTS_ERROR_EXIT,"Internal error, sizing unrecognized object in "
"(d)ets:match compilation.");
}
+
+ n = arityval(tpl[0]);
+ sum += 1 + n;
+ for (i = 1; i <= n; ++i)
+ sum += my_size_object(tpl[i], 0);
break;
} else if (is_map(t)) {
if (is_flatmap(t)) {
@@ -5711,7 +5717,7 @@ static Uint my_size_object(Eterm t)
n = arityval(p[0]);
sum += 1 + n;
for (int i = 1; i <= n; ++i)
- sum += my_size_object(p[i]);
+ sum += my_size_object(p[i], 0);
/* Calculate size of values */
p = (Eterm *)mp;
@@ -5719,18 +5725,19 @@ static Uint my_size_object(Eterm t)
sum += n + 3;
p += 3; /* hdr + size + keys words */
while (n--) {
- sum += my_size_object(*p++);
+ sum += my_size_object(*p++, 0);
}
} else {
Eterm *head = (Eterm *)hashmap_val(t);
Eterm hdr = *head;
Uint sz;
+
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
sum += 1 + sz + header_arity(hdr);
head += 1 + header_arity(hdr);
while(sz-- > 0) {
- sum += my_size_object(head[sz]);
+ sum += my_size_object(head[sz], 1);
}
}
break;
@@ -5743,46 +5750,54 @@ static Uint my_size_object(Eterm t)
return sum;
}
-static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
+static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap,
+ int is_hashmap_node)
{
Eterm ret = NIL, a, b;
Eterm *p;
Uint sz;
switch (t & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_LIST:
- a = my_copy_struct(CAR(list_val(t)), hp, off_heap);
- b = my_copy_struct(CDR(list_val(t)), hp, off_heap);
+ a = my_copy_struct(CAR(list_val(t)), hp, off_heap, 0);
+ b = my_copy_struct(CDR(list_val(t)), hp, off_heap, 0);
ret = CONS(*hp, a, b);
*hp += 2;
break;
case TAG_PRIMARY_BOXED:
if (is_tuple(t)) {
- if (tuple_val(t)[0] == make_arityval(1) &&
- is_tuple(a = tuple_val(t)[1])) {
- Uint i,n;
- p = tuple_val(a);
- n = arityval(p[0]);
- if (n == 0) {
- ret = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
- } else {
- Eterm *savep = *hp;
- ret = make_tuple(savep);
- *hp += n + 1;
- *savep++ = make_arityval(n);
- for(i = 1; i <= n; ++i)
- *savep++ = my_copy_struct(p[i], hp, off_heap);
- }
+ Eterm* tpl = tuple_val(t);
+ Uint i,n;
+ Eterm *savep;
+
+ if (is_hashmap_node) {
+ /* hashmap collision node, no matchspec syntax here */
+ }
+ else if (tpl[0] == make_arityval(1) && is_tuple(tpl[1])) {
+ /* A {{...}} expression */
+ tpl = tuple_val(tpl[1]);
}
- else if (tuple_val(t)[0] == make_arityval(2) &&
- tuple_val(t)[1] == am_const) {
+ else if (tpl[0] == make_arityval(2) && tpl[1] == am_const) {
/* A {const, XXX} expression */
- b = tuple_val(t)[2];
+ b = tpl[2];
sz = size_object(b);
ret = copy_struct(b,sz,hp,off_heap);
+ break;
} else {
erts_exit(ERTS_ERROR_EXIT, "Trying to constant-copy non constant expression "
"0x%bex in (d)ets:match compilation.", t);
}
+ n = arityval(tpl[0]);
+ if (n == 0) {
+ ret = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ savep = *hp;
+ ret = make_tuple(savep);
+ *hp += n + 1;
+ *savep++ = tpl[0];
+ for(i = 1; i <= n; ++i)
+ *savep++ = my_copy_struct(tpl[i], hp, off_heap, 0);
+ }
+
} else if (is_map(t)) {
if (is_flatmap(t)) {
Uint i,n;
@@ -5803,7 +5818,7 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
*hp += n + 1;
*savep++ = make_arityval(n);
for(i = 1; i <= n; ++i)
- *savep++ = my_copy_struct(p[i], hp, off_heap);
+ *savep++ = my_copy_struct(p[i], hp, off_heap, 0);
}
savep = *hp;
ret = make_flatmap(savep);
@@ -5815,7 +5830,7 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
*savep++ = keys;
p += 3; /* hdr + size + keys words */
for (i = 0; i < n; i++)
- *savep++ = my_copy_struct(p[i], hp, off_heap);
+ *savep++ = my_copy_struct(p[i], hp, off_heap, 0);
erts_usort_flatmap((flatmap_t*)flatmap_val(ret));
} else {
Eterm *head = hashmap_val(t);
@@ -5832,7 +5847,7 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
*savep++ = *head++; /* map size */
for (int i = 0; i < sz; i++) {
- *savep++ = my_copy_struct(head[i],hp,off_heap);
+ *savep++ = my_copy_struct(head[i],hp,off_heap, 1);
}
}
} else {
diff --git a/erts/emulator/beam/erl_drv_thread.c b/erts/emulator/beam/erl_drv_thread.c
index 949d89232a..c8e6b9906b 100644
--- a/erts/emulator/beam/erl_drv_thread.c
+++ b/erts/emulator/beam/erl_drv_thread.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2007-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2007-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -609,6 +609,7 @@ erl_drv_thread_create(char *name,
struct ErlDrvTid_ *dtid;
ethr_thr_opts ethr_opts = ETHR_THR_OPTS_DEFAULT_INITER;
ethr_thr_opts *use_opts;
+ char name_buff[ETHR_THR_NAME_MAX + 1];
if (!opts && !name)
use_opts = NULL;
@@ -616,7 +617,8 @@ erl_drv_thread_create(char *name,
if(opts)
ethr_opts.suggested_stack_size = opts->suggested_stack_size;
- ethr_opts.name = name;
+ erts_snprintf(name_buff, sizeof(name_buff), "%s", name);
+ ethr_opts.name = name_buff;
use_opts = &ethr_opts;
}
diff --git a/erts/emulator/beam/erl_fun.h b/erts/emulator/beam/erl_fun.h
index 43f3ec3b22..a67afaceeb 100644
--- a/erts/emulator/beam/erl_fun.h
+++ b/erts/emulator/beam/erl_fun.h
@@ -74,14 +74,15 @@ typedef struct erl_fun_thing {
/* -- The following may be compound Erlang terms ---------------------- */
Eterm creator; /* Pid of creator process (contains node). */
- Eterm env[1]; /* Environment (free variables). */
+ Eterm env[]; /* Environment (free variables). */
} ErlFunThing;
#define is_local_fun(FunThing) ((FunThing)->creator != am_external)
#define is_external_fun(FunThing) ((FunThing)->creator == am_external)
-/* ERL_FUN_SIZE does _not_ include space for the environment */
-#define ERL_FUN_SIZE ((sizeof(ErlFunThing)/sizeof(Eterm))-1)
+/* ERL_FUN_SIZE does _not_ include space for the environment which is a
+ * C99-style flexible array */
+#define ERL_FUN_SIZE ((sizeof(ErlFunThing)/sizeof(Eterm)))
ErlFunThing *erts_new_export_fun_thing(Eterm **hpp, Export *exp, int arity);
ErlFunThing *erts_new_local_fun_thing(Process *p,
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 8a8265968a..337567406b 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -95,8 +95,8 @@ static Uint hashmap_subtree_size(Eterm node);
static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key, Eterm node, Eterm *value);
static Eterm flatmap_from_validated_list(Process *p, Eterm list, Eterm fill_value, Uint size);
static Eterm hashmap_from_unsorted_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int reject_dupkeys, ErtsAlcType_t temp_memory_allocator);
-static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, int is_root, ErtsAlcType_t temp_memory_allocator);
-static Eterm hashmap_from_chunked_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, Uint size, int is_root, ErtsAlcType_t temp_memory_allocator);
+static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, ErtsAlcType_t temp_memory_allocator);
+static Eterm hashmap_from_chunked_array(ErtsHeapFactory*, hxnode_t *hxns, Uint n, Uint size, ErtsAlcType_t temp_memory_allocator);
static Eterm hashmap_info(Process *p, Eterm node);
static Eterm hashmap_bld_tuple_uint(Uint **hpp, Uint *szp, Uint n, Uint nums[]);
static int hxnodecmp(const void* a, const void* b);
@@ -112,8 +112,7 @@ static int hxnodecmpkey(const void* a, const void* b);
#define maskval(V,L) (((V) >> ((7 - (L))*4)) & 0xf)
#define DBG_PRINT(X)
/*erts_printf X*/
-#define HALLOC_EXTRA_HASHMAP_FROM_CHUNKED_ARRAY 200
-#define HALLOC_EXTRA HALLOC_EXTRA_HASHMAP_FROM_CHUNKED_ARRAY
+#define HALLOC_EXTRA 200
/* *******************************
* ** Yielding C Fun (YCF) Note **
* *******************************
@@ -135,7 +134,6 @@ static int hxnodecmpkey(const void* a, const void* b);
#include "erl_map.ycf.h"
#endif
#define NOT_YCF_YIELDING_VERSION 1
-#undef HALLOC_EXTRA
#define YCF_CONSUME_REDS(X) while(0){}
void erts_init_map(void) {
@@ -282,6 +280,7 @@ BIF_RETTYPE map_get_2(BIF_ALIST_2) {
* means that the code has to follow some restrictions. See note about
* YCF near the top of the file for more information.
*/
+
#ifdef INCLUDE_YCF_TRANSFORMED_ONLY_FUNCTIONS
static BIF_RETTYPE maps_from_keys_2_helper(Process* p, Eterm* bif_args) {
Eterm list = bif_args[0];
@@ -677,33 +676,20 @@ Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n,
static ERTS_INLINE Eterm
from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks, Eterm *vs,
- Uint n, Eterm *key_tuple, flatmap_t **fmpp)
+ Uint n, flatmap_t **fmpp)
{
if (n <= MAP_SMALL_MAP_LIMIT) {
Eterm *hp;
flatmap_t *fmp;
Eterm keys;
- if (key_tuple && is_value(*key_tuple)) {
- keys = *key_tuple;
- hp = erts_produce_heap(factory, MAP_HEADER_FLATMAP_SZ + n, 0);
- ASSERT(is_tuple_arity(keys, n));
- ASSERT(n == 0 || sys_memcmp((void *) (tuple_val(keys) + 1),
- (void *) ks,
- n * sizeof(Eterm)) == 0);
- }
- else if (n == 0) {
+ if (n == 0) {
keys = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
- if (key_tuple)
- *key_tuple = keys;
hp = erts_produce_heap(factory, MAP_HEADER_FLATMAP_SZ + n, 0);
}
else {
hp = erts_produce_heap(factory, 1 + MAP_HEADER_FLATMAP_SZ + 2*n, 0);
keys = make_tuple(hp);
- if (key_tuple) {
- *key_tuple = keys;
- }
*hp++ = make_arityval(n);
sys_memcpy((void *) hp,
(void *) ks,
@@ -720,15 +706,10 @@ from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks, Eterm *vs,
sys_memcpy((void *) hp, (void *) vs, n * sizeof(Eterm));
- if (fmpp) {
- *fmpp = fmp;
- return THE_NON_VALUE;
- }
- return make_flatmap(fmp);
+ *fmpp = fmp;
+ return THE_NON_VALUE;
} else {
- if (fmpp) {
- *fmpp = NULL;
- }
+ *fmpp = NULL;
return erts_hashmap_from_ks_and_vs(factory, ks, vs, n);
}
}
@@ -738,7 +719,7 @@ Eterm erts_map_from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks, Eterm *vs, Ui
Eterm res;
flatmap_t *fmp;
- res = from_ks_and_vs(factory, ks, vs, n, NULL, &fmp);
+ res = from_ks_and_vs(factory, ks, vs, n, &fmp);
if (fmp) {
if (erts_validate_and_sort_flatmap(fmp)) {
res = make_flatmap(fmp);
@@ -806,14 +787,7 @@ static Eterm hashmap_from_unsorted_array(ErtsHeapFactory* factory,
Uint cx;
Eterm res;
- if (n == 0) {
- Eterm *hp;
- hp = erts_produce_heap(factory, 2, 0);
- hp[0] = MAP_HEADER_HAMT_HEAD_BITMAP(0);
- hp[1] = 0;
-
- return make_hashmap(hp);
- }
+ ASSERT(n > 0);
/* sort and compact array (remove non-unique entries) */
erts_qsort(hxns, n, sizeof(hxnode_t), hxnodecmp);
@@ -823,7 +797,7 @@ static Eterm hashmap_from_unsorted_array(ErtsHeapFactory* factory,
if (hxns[ix].hx == hxns[ix+1].hx) {
/* find region of equal hash values */
- jx = ix + 1;
+ jx = ix + 2;
while(jx < n && hxns[ix].hx == hxns[jx].hx) { jx++; }
/* find all correct keys from region
* (last in list but now hash sorted so we check highest id instead) */
@@ -866,7 +840,8 @@ static Eterm hashmap_from_unsorted_array(ErtsHeapFactory* factory,
if (cx > 1) {
/* recursive decompose array */
- res = hashmap_from_sorted_unique_array(factory, hxns, cx, 0, temp_memory_allocator);
+ res = hashmap_from_sorted_unique_array(factory, hxns, cx,
+ temp_memory_allocator);
} else {
Eterm *hp;
@@ -893,51 +868,49 @@ static Eterm hashmap_from_unsorted_array(ErtsHeapFactory* factory,
* YCF near the top of the file for more information.
*/
static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory* factory,
- hxnode_t *hxns, Uint n, int lvl,
+ hxnode_t *hxns, Uint n,
ErtsAlcType_t temp_memory_allocator) {
Eterm res = NIL;
- Uint i;
Uint ix;
- Uint jx;
Uint elems;
- Uint32 sw;
- Uint32 hx;
- Eterm val;
hxnode_t *tmp = NULL;
- ASSERT(lvl < 32);
+
ix = 0;
elems = 1;
while (ix < n - 1) {
if (hxns[ix].hx == hxns[ix+1].hx) {
- jx = ix + 1;
- while (jx < n && hxns[ix].hx == hxns[jx].hx) { jx++; }
- tmp = (hxnode_t *)erts_alloc(temp_memory_allocator, ((jx - ix)) * sizeof(hxnode_t));
-
- for(i = 0; i < jx - ix; i++) {
- val = hxns[i + ix].val;
- hx = hashmap_restore_hash(lvl + 8, CAR(list_val(val)));
- swizzle32(sw,hx);
- tmp[i].hx = sw;
- tmp[i].val = val;
- tmp[i].i = i;
- tmp[i].skip = 1;
- }
+ Uint n_colliders;
+ Eterm* hp;
+ Eterm collision_node;
+ Uint jx = ix + 2;
+ Uint i;
+
+ while (jx < n && hxns[ix].hx == hxns[jx].hx)
+ jx++;
+
+ n_colliders = jx - ix;
+ hp = erts_produce_heap(factory, HAMT_COLLISION_NODE_SZ(n_colliders),
+ HALLOC_EXTRA);
+ collision_node = make_tuple(hp);
+
+ *hp++ = MAP_HEADER_HAMT_COLLISION_NODE(n_colliders);
+ for (i = 0; i < n_colliders; i++) {
+ *hp++ = hxns[ix + i].val;
+ ASSERT(i == 0
+ || CMP_TERM(CAR(list_val(hxns[ix+i-1].val)),
+ CAR(list_val(hxns[ix+i].val))) < 0);
+ }
- erts_qsort(tmp, jx - ix, sizeof(hxnode_t), hxnodecmp);
+ hxns[ix].val = collision_node;
+ hxns[ix].skip = n_colliders;
+ ix = jx;
- hxns[ix].skip = jx - ix;
- hxns[ix].val =
- hashmap_from_sorted_unique_array(factory, tmp, jx - ix, lvl + 8, temp_memory_allocator);
- erts_free(temp_memory_allocator, (void *) tmp);
- /* Memory management depend on the statement below */
- tmp = NULL;
- ix = jx;
- if (ix < n) { elems++; }
- continue;
+ if (ix < n) { elems++; }
+ continue;
}
- hxns[ix].skip = 1;
- elems++;
- ix++;
+ hxns[ix].skip = 1;
+ elems++;
+ ix++;
}
YCF_SPECIAL_CODE_START(ON_DESTROY_STATE);
{
@@ -948,14 +921,13 @@ static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory* factory,
}
}
YCF_SPECIAL_CODE_END();
- res = hashmap_from_chunked_array(factory, hxns, elems, n, !lvl, temp_memory_allocator);
+ res = hashmap_from_chunked_array(factory, hxns, elems, n, temp_memory_allocator);
ERTS_FACTORY_HOLE_CHECK(factory);
return res;
}
-#define HALLOC_EXTRA HALLOC_EXTRA_HASHMAP_FROM_CHUNKED_ARRAY
/* **Important Note**
*
* A yielding version of this function is generated with YCF. This
@@ -963,7 +935,7 @@ static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory* factory,
* YCF near the top of the file for more information.
*/
static Eterm hashmap_from_chunked_array(ErtsHeapFactory *factory, hxnode_t *hxns, Uint n,
- Uint size, int is_root,
+ Uint size,
ErtsAlcType_t temp_memory_allocator) {
Uint ix;
Uint d;
@@ -1015,16 +987,11 @@ static Eterm hashmap_from_chunked_array(ErtsHeapFactory *factory, hxnode_t *hxns
}
slot = maskval(v,0);
- hp = erts_produce_heap(factory, (is_root ? 3 : 2), 0);
+ hp = erts_produce_heap(factory, 3, 0);
- if (is_root) {
- hp[0] = MAP_HEADER_HAMT_HEAD_BITMAP(1 << slot);
- hp[1] = size;
- hp[2] = res;
- } else {
- hp[0] = MAP_HEADER_HAMT_NODE_BITMAP(1 << slot);
- hp[1] = res;
- }
+ hp[0] = MAP_HEADER_HAMT_HEAD_BITMAP(1 << slot);
+ hp[1] = size;
+ hp[2] = res;
return make_hashmap(hp);
}
@@ -1186,15 +1153,11 @@ static Eterm hashmap_from_chunked_array(ErtsHeapFactory *factory, hxnode_t *hxns
bp = 1 << slot;
hdr |= bp;
sz = hashmap_bitcount(hdr);
- hp = erts_produce_heap(factory, sz + /* hdr + item */ (is_root ? 2 : 1), 0);
+ hp = erts_produce_heap(factory, sz + /* hdr + item */ 2, 0);
nhp = hp;
- if (is_root) {
- *hp++ = (hdr == 0xffff) ? MAP_HEADER_HAMT_HEAD_ARRAY : MAP_HEADER_HAMT_HEAD_BITMAP(hdr);
- *hp++ = size;
- } else {
- *hp++ = MAP_HEADER_HAMT_NODE_BITMAP(hdr);
- }
+ *hp++ = (hdr == 0xffff) ? MAP_HEADER_HAMT_HEAD_ARRAY : MAP_HEADER_HAMT_HEAD_BITMAP(hdr);
+ *hp++ = size;
*hp++ = res; sz--;
while (sz--) { *hp++ = ESTACK_POP(stack); }
@@ -1206,7 +1169,6 @@ static Eterm hashmap_from_chunked_array(ErtsHeapFactory *factory, hxnode_t *hxns
ERTS_FACTORY_HOLE_CHECK(factory);
return res;
}
-#undef HALLOC_EXTRA
static int hxnodecmpkey(const void *va, const void *vb) {
const hxnode_t *a = (const hxnode_t*) va;
@@ -1555,9 +1517,57 @@ BIF_RETTYPE maps_merge_trap_1(BIF_ALIST_1) {
(HashmapMergeContext*) ERTS_MAGIC_BIN_DATA(ctx_bin));
}
-#define HALLOC_EXTRA 200
#define MAP_MERGE_LOOP_FACTOR 8
+static Eterm merge_collision_node(Process* p,
+ Eterm* srcA, Uint szA,
+ Eterm* srcB, Uint szB,
+ Uint* map_sizep)
+{
+ Eterm *hp;
+ Eterm *hdr_ptr;
+ Eterm *hp_end;
+ Uint arity;
+
+ ERTS_ASSERT(szA >= 1 && szB >= 1);
+ arity = szA + szB;
+ hp = HAlloc(p, HAMT_COLLISION_NODE_SZ(arity));
+ hp_end = hp + HAMT_COLLISION_NODE_SZ(arity);
+ hdr_ptr = hp++;
+
+ while (szA && szB) {
+ Eterm keyA = CAR(list_val(*srcA));
+ Eterm keyB = CAR(list_val(*srcB));
+ const Sint key_cmp = CMP_TERM(keyA, keyB);
+
+ if (key_cmp < 0) {
+ *hp++ = *srcA++;
+ szA--;
+ }
+ else {
+ *hp++ = *srcB++;
+ szB--;
+ if (key_cmp == 0) {
+ srcA++;
+ szA--;
+ arity--;
+ (*map_sizep)--;
+ }
+ }
+ }
+ ASSERT(arity >= 2);
+
+ for ( ; szA; szA--)
+ *hp++ = *srcA++;
+ for ( ; szB; szB--)
+ *hp++ = *srcB++;
+
+ HRelease(p, hp_end, hp);
+ *hdr_ptr = make_arityval(arity);
+ return make_tuple(hdr_ptr);
+}
+
+
static BIF_RETTYPE hashmap_merge(Process *p, Eterm map_A, Eterm map_B,
int swap_args, HashmapMergeContext* ctx) {
#define PSTACK_TYPE struct HashmapMergePStackType
@@ -1571,6 +1581,7 @@ static BIF_RETTYPE hashmap_merge(Process *p, Eterm map_A, Eterm map_B,
Eterm trap_ret;
Sint initial_reds = (Sint) (ERTS_BIF_REDS_LEFT(p) * MAP_MERGE_LOOP_FACTOR);
Sint reds = initial_reds;
+ Uint coll_szA = 0, coll_szB = 0;
/*
* Strategy: Do depth-first traversal of both trees (at the same time)
@@ -1630,8 +1641,13 @@ recurse:
goto merge_nodes;
}
}
- hx = hashmap_restore_hash(ctx->lvl, keyA);
- sp->abm = 1 << hashmap_index(hx);
+ if (ctx->lvl < HAMT_MAX_LEVEL) {
+ hx = hashmap_restore_hash(ctx->lvl, keyA);
+ sp->abm = 1 << hashmap_index(hx);
+ }
+ else {
+ coll_szA = 1;
+ }
/* keep srcA pointing at the leaf */
}
else { /* A is NODE */
@@ -1640,25 +1656,35 @@ recurse:
ASSERT(is_header(hdrA));
switch (hdrA & _HEADER_MAP_SUBTAG_MASK) {
case HAMT_SUBTAG_HEAD_ARRAY: {
+ ASSERT(ctx->lvl < HAMT_MAX_LEVEL);
sp->srcA++;
sp->abm = 0xffff;
break;
}
case HAMT_SUBTAG_HEAD_BITMAP: sp->srcA++;
case HAMT_SUBTAG_NODE_BITMAP: {
+ ASSERT(ctx->lvl < HAMT_MAX_LEVEL);
sp->abm = MAP_HEADER_VAL(hdrA);
break;
}
- default:
- erts_exit(ERTS_ABORT_EXIT, "bad header %ld\r\n", hdrA);
+ default: /* collision node */
+ ERTS_ASSERT(is_arity_value(hdrA));
+ ASSERT(ctx->lvl == HAMT_MAX_LEVEL);
+ coll_szA = arityval(hdrA);
+ ASSERT(coll_szA >= 2);
}
}
if (is_list(sp->nodeB)) { /* B is LEAF */
Eterm keyB = CAR(list_val(sp->nodeB));
- hx = hashmap_restore_hash(ctx->lvl, keyB);
- sp->bbm = 1 << hashmap_index(hx);
+ if (ctx->lvl < HAMT_MAX_LEVEL) {
+ hx = hashmap_restore_hash(ctx->lvl, keyB);
+ sp->bbm = 1 << hashmap_index(hx);
+ }
+ else {
+ coll_szB = 1;
+ }
/* keep srcB pointing at the leaf */
}
else { /* B is NODE */
@@ -1667,17 +1693,22 @@ recurse:
ASSERT(is_header(hdrB));
switch (hdrB & _HEADER_MAP_SUBTAG_MASK) {
case HAMT_SUBTAG_HEAD_ARRAY: {
+ ASSERT(ctx->lvl < HAMT_MAX_LEVEL);
sp->srcB++;
sp->bbm = 0xffff;
break;
}
case HAMT_SUBTAG_HEAD_BITMAP: sp->srcB++;
case HAMT_SUBTAG_NODE_BITMAP: {
+ ASSERT(ctx->lvl < HAMT_MAX_LEVEL);
sp->bbm = MAP_HEADER_VAL(hdrB);
break;
}
- default:
- erts_exit(ERTS_ABORT_EXIT, "bad header %ld\r\n", hdrB);
+ default: /* collision node */
+ ERTS_ASSERT(is_arity_value(hdrB));
+ ASSERT(ctx->lvl == HAMT_MAX_LEVEL);
+ coll_szB = arityval(hdrB);
+ ASSERT(coll_szB >= 2);
}
}
}
@@ -1701,13 +1732,22 @@ merge_nodes:
sp->srcA++;
sp->srcB++;
}
- } else { /* Start build a node */
+ }
+ else if (ctx->lvl < HAMT_MAX_LEVEL) { /* Start build a node */
sp->ix = 0;
sp->rbm = sp->abm | sp->bbm;
ASSERT(!(sp->rbm == 0 && ctx->lvl > 0));
}
+ else {
+ res = merge_collision_node(p, sp->srcA, coll_szA,
+ sp->srcB, coll_szB, &ctx->size);
+ sp->mix = 3;
+ coll_szA = coll_szB = 0;
+ continue;
+ }
if (--reds <= 0) {
+ ASSERT(!coll_szA && !coll_szB);
goto trap;
}
resume_from_trap:
@@ -1851,21 +1891,14 @@ static int hash_cmp(Uint32 ha, Uint32 hb)
int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp)
{
- unsigned int lvl = 0;
-
if (ap && bp) {
+ Uint32 ha, hb;
ASSERT(CMP_TERM(CAR(ap), CAR(bp)) != 0);
- for (;;) {
- Uint32 ha = hashmap_restore_hash(lvl, CAR(ap));
- Uint32 hb = hashmap_restore_hash(lvl, CAR(bp));
- int cmp = hash_cmp(ha, hb);
- if (cmp) {
- return cmp;
- }
- lvl += 8;
- }
+ ha = hashmap_make_hash(CAR(ap));
+ hb = hashmap_make_hash(CAR(bp));
+ return hash_cmp(ha, hb);
}
-
+ ASSERT(ap || bp);
return ap ? -1 : 1;
}
@@ -2300,7 +2333,9 @@ Uint hashmap_node_size(Eterm hdr, Eterm **nodep)
ASSERT(sz < 17);
break;
default:
- erts_exit(ERTS_ABORT_EXIT, "bad header");
+ ERTS_ASSERT(is_arity_value(hdr));
+ sz = arityval(hdr);
+ break;
}
return sz;
}
@@ -2394,7 +2429,7 @@ Eterm* hashmap_iterator_prev(ErtsWStack* s) {
const Eterm *
erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
{
- Eterm *ptr, hdr, *res;
+ Eterm *ptr, hdr;
Uint ix, lvl = 0;
Uint32 hval,bp;
@@ -2405,15 +2440,16 @@ erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
ASSERT(is_hashmap_header_head(hdr));
ptr++;
- for (;;) {
+ do {
+ ASSERT(lvl == 0 || is_hashmap_header_node(hdr));
+
hval = MAP_HEADER_VAL(hdr);
ix = hashmap_index(hx);
if (hval != 0xffff) {
bp = 1 << ix;
if (!(bp & hval)) {
/* not occupied */
- res = NULL;
- break;
+ return NULL;
}
ix = hashmap_bitcount(hval & (bp - 1));
}
@@ -2421,8 +2457,7 @@ erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
if (is_list(node)) { /* LEAF NODE [K|V] */
ptr = list_val(node);
- res = EQ(CAR(ptr), key) ? &(CDR(ptr)) : NULL;
- break;
+ return EQ(CAR(ptr), key) ? &(CDR(ptr)) : NULL;
}
hx = hashmap_shift_hash(hx,lvl,key);
@@ -2431,10 +2466,17 @@ erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
ptr = boxed_val(node);
hdr = *ptr;
ASSERT(is_header(hdr));
- ASSERT(!is_hashmap_header_head(hdr));
- }
+ } while (!is_arity_value(hdr));
- return res;
+ /* collision node */
+ ix = arityval(hdr);
+ ASSERT(ix > 1);
+ do {
+ Eterm* kv = list_val(*(++ptr));
+ if (EQ(CAR(kv), key))
+ return &(CDR(kv));
+ } while (--ix > 0);
+ return NULL;
}
Eterm erts_hashmap_insert(Process *p, Uint32 hx, Eterm key, Eterm value,
@@ -2448,6 +2490,8 @@ Eterm erts_hashmap_insert(Process *p, Uint32 hx, Eterm key, Eterm value,
/* We are putting a new value (under a new or existing key) */
hp = HAlloc(p, size);
res = erts_hashmap_insert_up(hp, key, value, upsz, &stack);
+ ASSERT(hashmap_val(res) + 2 + hashmap_bitcount(MAP_HEADER_VAL(*hashmap_val(res)))
+ == hp + size);
}
else {
/* We are putting the same key-value */
@@ -2555,9 +2599,34 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm value, Eterm node, Uint
}
size += HAMT_HEAD_BITMAP_SZ(n+1);
goto unroll;
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header tag %ld\r\n", hdr & _HEADER_MAP_SUBTAG_MASK);
- break;
+ default:
+ ERTS_ASSERT(is_arity_value(hdr));
+ n = arityval(hdr);
+ ASSERT(n >= 2);
+ for (slot = 0; slot < n; slot++) {
+ Eterm* kv = list_val(ptr[1+slot]);
+ Sint c;
+ ckey = CAR(kv);
+ c = CMP_TERM(key, ckey);
+ if (c == 0) {
+ if (CDR(ptr) == value) {
+ *sz = 0;
+ return 1;
+ }
+ *update_size = 0;
+ size += HAMT_COLLISION_NODE_SZ(n);
+ ESTACK_PUSH3(*sp, slot, 0, node);
+ goto unroll;
+ }
+ if (c < 0)
+ break;
+ }
+ if (is_update) {
+ return 0;
+ }
+ size += HAMT_COLLISION_NODE_SZ(n+1);
+ ESTACK_PUSH3(*sp, slot, 1, node);
+ goto unroll;
}
break;
default:
@@ -2566,21 +2635,25 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm value, Eterm node, Uint
}
}
insert_subnodes:
- clvl = lvl;
- chx = hashmap_restore_hash(clvl,ckey);
- size += HAMT_NODE_BITMAP_SZ(2);
- ix = hashmap_index(hx);
- cix = hashmap_index(chx);
-
- while (cix == ix) {
- ESTACK_PUSH4(*sp, 0, 1 << ix, 0, MAP_HEADER_HAMT_NODE_BITMAP(0));
- size += HAMT_NODE_BITMAP_SZ(1);
- hx = hashmap_shift_hash(hx,lvl,key);
- chx = hashmap_shift_hash(chx,clvl,ckey);
- ix = hashmap_index(hx);
- cix = hashmap_index(chx);
- }
- ESTACK_PUSH3(*sp, cix, ix, node);
+ if (lvl < HAMT_MAX_LEVEL) {
+ clvl = lvl;
+ chx = hashmap_restore_hash(clvl,ckey);
+ do {
+ ix = hashmap_index(hx);
+ cix = hashmap_index(chx);
+ if (cix != ix) {
+ size += HAMT_NODE_BITMAP_SZ(2);
+ ESTACK_PUSH4(*sp, cix, ix, 0, node);
+ goto unroll;
+ }
+ ESTACK_PUSH4(*sp, 0, 1 << ix, 0, MAP_HEADER_HAMT_NODE_BITMAP(0));
+ size += HAMT_NODE_BITMAP_SZ(1);
+ hx = hashmap_shift_hash(hx,lvl,key);
+ chx = hashmap_shift_hash(chx,clvl,ckey);
+ } while (lvl < HAMT_MAX_LEVEL);
+ }
+ size += HAMT_COLLISION_NODE_SZ(2);
+ ESTACK_PUSH2(*sp, 1, node);
unroll:
*sz = size + /* res cons */ 2;
@@ -2594,17 +2667,29 @@ Eterm erts_hashmap_insert_up(Eterm *hp, Eterm key, Eterm value,
Eterm *nhp = NULL;
Uint32 ix, cix, bp, hval;
Uint slot, n;
- /* Needed for halfword */
- DeclareTmpHeapNoproc(fake,1);
- UseTmpHeapNoproc(1);
+ Eterm fake;
res = CONS(hp, key, value); hp += 2;
do {
node = ESTACK_POP(*sp);
switch(primary_tag(node)) {
- case TAG_PRIMARY_LIST:
- ix = (Uint32) ESTACK_POP(*sp);
+ case TAG_PRIMARY_LIST: {
+ const int is_collision_node = (int) ESTACK_POP(*sp);
+ if (is_collision_node) {
+ nhp = hp;
+ *hp++ = MAP_HEADER_HAMT_COLLISION_NODE(2);
+ if (CMP_TERM(key, CAR(list_val(node))) < 0){
+ *hp++ = res;
+ *hp++ = node;
+ } else {
+ *hp++ = node;
+ *hp++ = res;
+ }
+ res = make_hashmap(nhp);
+ break;
+ }
+ ix = (Uint32)ESTACK_POP(*sp);
cix = (Uint32) ESTACK_POP(*sp);
nhp = hp;
@@ -2618,10 +2703,11 @@ Eterm erts_hashmap_insert_up(Eterm *hp, Eterm key, Eterm value,
}
res = make_hashmap(nhp);
break;
+ }
case TAG_PRIMARY_HEADER:
/* subnodes, fake it */
- *fake = node;
- node = make_boxed(fake);
+ fake = node;
+ node = make_boxed(&fake);
case TAG_PRIMARY_BOXED:
ptr = boxed_val(node);
hdr = *ptr;
@@ -2674,9 +2760,27 @@ Eterm erts_hashmap_insert_up(Eterm *hp, Eterm key, Eterm value,
}
res = make_hashmap(nhp);
break;
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header tag %x\r\n", hdr & _HEADER_MAP_SUBTAG_MASK);
- break;
+ default: {
+ int is_insert;
+ ERTS_ASSERT(is_arity_value(hdr));
+ n = arityval(hdr);
+ ASSERT(n >= 2);
+ is_insert = (int) ESTACK_POP(*sp);
+ slot = (Uint) ESTACK_POP(*sp);
+ nhp = hp;
+ n += is_insert;
+ *hp++ = MAP_HEADER_HAMT_COLLISION_NODE(n); ptr++;
+ ix = 0;
+ while (ix++ < slot)
+ *hp++ = *ptr++;
+ *hp++ = res;
+ if (!is_insert)
+ ptr++;
+ while (ix++ < n)
+ *hp++ = *ptr++;
+ res = make_hashmap(nhp);
+ break;
+ }
}
break;
default:
@@ -2855,9 +2959,22 @@ static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key,
/* not occupied */
res = THE_NON_VALUE;
goto not_found;
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header tag %ld\r\n", hdr & _HEADER_MAP_SUBTAG_MASK);
- break;
+ default: /* collision node */
+ ERTS_ASSERT(is_arity_value(hdr));
+ n = arityval(hdr);
+ ASSERT(n >= 2);
+ for (slot = 0; slot < n; slot++) {
+ Eterm* kv = list_val(ptr[1+slot]);
+ if (EQ(key, CAR(kv))) {
+ if (value)
+ *value = CDR(kv);
+ ESTACK_PUSH2(stack, slot, node);
+ size += HAMT_COLLISION_NODE_SZ(n);
+ goto unroll;
+ }
+ }
+ res = THE_NON_VALUE;
+ goto not_found;
}
break;
default:
@@ -3039,8 +3156,25 @@ unroll:
}
res = make_hashmap(nhp);
break;
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header tag %x\r\n", hdr & _HEADER_MAP_SUBTAG_MASK);
+ default: /* collision node */
+ ERTS_ASSERT(is_arity_value(hdr));
+ n = arityval(hdr);
+ ASSERT(n >= 2);
+ slot = (Uint) ESTACK_POP(stack);
+ ASSERT(slot < n);
+ if (n > 2) { /* Shrink collision node */
+ nhp = hp;
+ *hp++ = MAP_HEADER_HAMT_COLLISION_NODE(n-1); ptr++;
+ n -= slot + 1;
+ while (slot--) { *hp++ = *ptr++; }
+ ptr++;
+ while(n--) { *hp++ = *ptr++; }
+ res = make_hashmap(nhp);
+ }
+ else { /* Collapse collision node */
+ ASSERT(res == THE_NON_VALUE);
+ res = ptr[1 + (1-slot)];
+ }
break;
}
} while(!ESTACK_ISEMPTY(stack));
@@ -3315,8 +3449,10 @@ BIF_RETTYPE erts_internal_map_hashmap_children_1(BIF_ALIST_1) {
sz = 16;
ptr += 2;
break;
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header\r\n");
+ default: /* collision node */
+ ERTS_ASSERT(is_arity_value(hdr));
+ sz = arityval(hdr);
+ ASSERT(sz >= 2);
break;
}
ASSERT(sz < 17);
@@ -3338,15 +3474,17 @@ static Eterm hashmap_info(Process *p, Eterm node) {
DECL_AM(leafs);
DECL_AM(bitmaps);
DECL_AM(arrays);
- Uint nleaf=0, nbitmap=0, narray=0;
- Uint bitmap_usage[16], leaf_usage[16];
- Uint lvl = 0, clvl;
+ DECL_AM(collisions);
+ Uint nleaf=0, nbitmap=0, narray=0, ncollision = 0;
+ Uint bitmap_usage[16];
+ Uint collision_usage[16];
+ Uint leaf_usage[HAMT_MAX_LEVEL + 2];
+ Uint max_depth = 0, clvl;
DECLARE_ESTACK(stack);
- for (sz = 0; sz < 16; sz++) {
- bitmap_usage[sz] = 0;
- leaf_usage[sz] = 0;
- }
+ sys_memzero(bitmap_usage, sizeof(bitmap_usage));
+ sys_memzero(collision_usage, sizeof(collision_usage));
+ sys_memzero(leaf_usage, sizeof(leaf_usage));
ptr = boxed_val(node);
ESTACK_PUSH(stack, 0);
@@ -3354,8 +3492,6 @@ static Eterm hashmap_info(Process *p, Eterm node) {
do {
node = ESTACK_POP(stack);
clvl = ESTACK_POP(stack);
- if (lvl < clvl)
- lvl = clvl;
switch(primary_tag(node)) {
case TAG_PRIMARY_LIST:
nleaf++;
@@ -3371,45 +3507,49 @@ static Eterm hashmap_info(Process *p, Eterm node) {
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
ASSERT(sz < 17);
bitmap_usage[sz-1] += 1;
- while(sz--) {
- ESTACK_PUSH(stack, clvl + 1);
- ESTACK_PUSH(stack, ptr[sz+1]);
- }
break;
case HAMT_SUBTAG_HEAD_BITMAP:
nbitmap++;
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
bitmap_usage[sz-1] += 1;
- while(sz--) {
- ESTACK_PUSH(stack, clvl + 1);
- ESTACK_PUSH(stack, ptr[sz+2]);
- }
+ ptr++;
break;
case HAMT_SUBTAG_HEAD_ARRAY:
narray++;
sz = 16;
- while(sz--) {
- ESTACK_PUSH(stack, clvl + 1);
- ESTACK_PUSH(stack, ptr[sz+2]);
- }
- break;
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header\r\n");
+ ptr++;
break;
+ default: /* collision node */
+ ERTS_ASSERT(is_arity_value(hdr));
+ ncollision++;
+ sz = arityval(hdr);
+ ASSERT(sz >= 2);
+ collision_usage[(sz > 16 ? 16 : sz) - 1] += 1;
+ break;
}
+ ASSERT(sz >= 1);
+ clvl++;
+ ASSERT(clvl <= HAMT_MAX_LEVEL+1);
+ if (max_depth < clvl)
+ max_depth = clvl;
+ while(sz--) {
+ ESTACK_PUSH(stack, clvl);
+ ESTACK_PUSH(stack, ptr[sz+1]);
+ }
}
} while(!ESTACK_ISEMPTY(stack));
/* size */
sz = 0;
- hashmap_bld_tuple_uint(NULL,&sz,16,leaf_usage);
- hashmap_bld_tuple_uint(NULL,&sz,16,bitmap_usage);
+ hashmap_bld_tuple_uint(NULL, &sz, HAMT_MAX_LEVEL+2, leaf_usage);
+ hashmap_bld_tuple_uint(NULL, &sz, 16, bitmap_usage);
+ hashmap_bld_tuple_uint(NULL, &sz, 16, collision_usage);
/* alloc */
- hp = HAlloc(p, 2+3 + 3*(2+4) + sz);
+ hp = HAlloc(p, 2+3 + 4*(2+4) + sz);
- info = hashmap_bld_tuple_uint(&hp,NULL,16,leaf_usage);
+ info = hashmap_bld_tuple_uint(&hp, NULL, HAMT_MAX_LEVEL+2, leaf_usage);
tup = TUPLE3(hp, AM_leafs, make_small(nleaf),info); hp += 4;
res = CONS(hp, tup, res); hp += 2;
@@ -3417,10 +3557,14 @@ static Eterm hashmap_info(Process *p, Eterm node) {
tup = TUPLE3(hp, AM_bitmaps, make_small(nbitmap), info); hp += 4;
res = CONS(hp, tup, res); hp += 2;
+ info = hashmap_bld_tuple_uint(&hp, NULL, 16, collision_usage);
+ tup = TUPLE3(hp, AM_collisions, make_small(ncollision), info); hp += 4;
+ res = CONS(hp, tup, res); hp += 2;
+
tup = TUPLE3(hp, AM_arrays, make_small(narray),NIL); hp += 4;
res = CONS(hp, tup, res); hp += 2;
- tup = TUPLE2(hp, AM_depth, make_small(lvl)); hp += 3;
+ tup = TUPLE2(hp, AM_depth, make_small(max_depth)); hp += 3;
res = CONS(hp, tup, res); hp += 2;
DESTROY_ESTACK(stack);
@@ -3448,12 +3592,16 @@ static Eterm hashmap_bld_tuple_uint(Uint **hpp, Uint *szp, Uint n, Uint nums[])
* Since each hashmap node can only be up to 16 elements
* large we use 4 bits per level in the path.
*
- * So a Path with value 0x110 will first get the 0:th
+ * So a Path with value 0x210 will first get the 0:th
* slot in the head node, and then the 1:st slot in the
- * resulting node and then finally the 1:st slot in the
+ * resulting node and then finally the 2:st slot in the
* node beneath. If that slot is not a leaf, then the path
* continues down the 0:th slot until it finds a leaf.
*
+ * Collision nodes may (theoretically and in debug) have more
+ * than 16 elements. To not complicate the 4-bit path format
+ * we avoid yielding in collision nodes.
+ *
* Once the leaf has been found, the return value is created
* by traversing the tree using the stack that was built
* when searching for the first leaf to return.
@@ -3596,7 +3744,12 @@ BIF_RETTYPE erts_internal_map_next_3(BIF_ALIST_3) {
Uint path_length = 0;
Uint *path_rest = NULL;
int i, elems, orig_elems;
- Eterm node = map, res, *patch_ptr = NULL, *hp;
+ Eterm node = map, res, *patch_ptr = NULL;
+ Eterm *hp = NULL;
+ Eterm *hp_end;
+ Eterm *ptr;
+ Uint sz, words_per_elem;
+ Uint idx;
/* A stack WSTACK is used when traversing the hashmap.
* It contains: node, idx, sz, ptr
@@ -3654,61 +3807,29 @@ BIF_RETTYPE erts_internal_map_next_3(BIF_ALIST_3) {
BIF_ERROR(BIF_P, BADARG);
}
- if (type == iterator) {
- /*
- * Iterator uses the format {K1, V1, {K2, V2, {K3, V3, [Path | Map]}}},
- * so each element is 4 words large.
- * To make iteration order independent of input reductions
- * the KV-pairs are here built in DESTRUCTIVE non-reverse order.
- */
- hp = HAlloc(BIF_P, 4 * elems);
- } else {
- /*
- * List used the format [Path, Map, {K3,V3}, {K2,V2}, {K1,V1} | BIF_ARG_3],
- * so each element is 2+3 words large.
- * To make list order independent of input reductions
- * the KV-pairs are here built in FUNCTIONAL reverse order
- * as this is how the list as a whole is constructed.
- */
- hp = HAlloc(BIF_P, (2 + 3) * elems);
- }
-
- orig_elems = elems;
-
/* First we look for the leaf to start at using the
path given. While doing so, we push each map node
and the index onto the stack to use later. */
for (i = 1; ; i++) {
- Eterm *ptr = hashmap_val(node),
- hdr = *ptr++;
- Uint sz;
+ Eterm hdr;
+
+ ptr = hashmap_val(node);
+ hdr = *ptr++;
sz = hashmap_node_size(hdr, &ptr);
- if (PATH_ELEM(curr_path) >= sz)
+ idx = PATH_ELEM(curr_path);
+ if (idx >= sz)
goto badarg;
- WSTACK_PUSH4(stack, node, PATH_ELEM(curr_path)+1, sz, (UWord)ptr);
-
- /* We have found a leaf, return it and the next X elements */
- if (is_list(ptr[PATH_ELEM(curr_path)])) {
- Eterm *lst = list_val(ptr[PATH_ELEM(curr_path)]);
- if (type == iterator) {
- res = make_tuple(hp);
- hp[0] = make_arityval(3);
- hp[1] = CAR(lst);
- hp[2] = CDR(lst);
- patch_ptr = &hp[3];
- hp += 4;
- } else {
- Eterm tup = TUPLE2(hp, CAR(lst), CDR(lst)); hp += 3;
- res = CONS(hp, tup, BIF_ARG_3); hp += 2;
- }
- elems--;
+ if (is_list(ptr[idx])) {
+ /* We have found a leaf, return it and the next X elements */
break;
}
- node = ptr[PATH_ELEM(curr_path)];
+ WSTACK_PUSH4(stack, node, idx+1, sz, (UWord)ptr);
+
+ node = ptr[idx];
curr_path >>= PATH_ELEM_SIZE;
@@ -3726,12 +3847,50 @@ BIF_RETTYPE erts_internal_map_next_3(BIF_ALIST_3) {
}
}
+ if (type == iterator) {
+ /*
+ * Iterator uses the format {K1, V1, {K2, V2, {K3, V3, [Path | Map]}}},
+ * so each element is 4 words large.
+ * To make iteration order independent of input reductions
+ * the KV-pairs are here built in DESTRUCTIVE non-reverse order.
+ */
+ words_per_elem = 4;
+ patch_ptr = &res;
+ } else {
+ /*
+ * List used the format [Path, Map, {K3,V3}, {K2,V2}, {K1,V1} | BIF_ARG_3],
+ * so each element is 2+3 words large.
+ * To make list order independent of input reductions
+ * the KV-pairs are here built in FUNCTIONAL reverse order
+ * as this is how the list as a whole is constructed.
+ */
+ words_per_elem = 2 + 3;
+ res = BIF_ARG_3;
+ }
+ hp = HAlloc(BIF_P, words_per_elem * elems);
+ hp_end = hp + words_per_elem * elems;
+
+ orig_elems = elems;
+
/* We traverse the hashmap and return at most `elems` elements */
while(1) {
- Eterm *ptr = (Eterm*)WSTACK_POP(stack);
- Uint sz = (Uint)WSTACK_POP(stack);
- Uint idx = (Uint)WSTACK_POP(stack);
- Eterm node = (Eterm)WSTACK_POP(stack);
+
+ if (idx == 0) {
+ if (elems < sz && is_arity_value(*hashmap_val(node))) {
+ /*
+ * This is a collision node!
+ * Make sure 'elems' is large enough not to yield in the
+ * middle of it. Collision nodes may be larger than 16
+ * and that would complicate the 4-bit path format.
+ */
+ elems = sz;
+ HRelease(BIF_P, hp_end, hp);
+ hp = HAlloc(BIF_P, words_per_elem * elems);
+ hp_end = hp + words_per_elem * elems;
+ }
+ }
+ else
+ ASSERT(!is_arity_value(*hashmap_val(node)));
while (idx < sz && elems != 0 && is_list(ptr[idx])) {
Eterm *lst = list_val(ptr[idx]);
@@ -3750,6 +3909,8 @@ BIF_RETTYPE erts_internal_map_next_3(BIF_ALIST_3) {
idx++;
}
+ ASSERT(idx == sz || !is_arity_value(*hashmap_val(node)));
+
if (elems == 0) {
if (idx < sz) {
/* There are more elements in this node to explore */
@@ -3768,26 +3929,29 @@ BIF_RETTYPE erts_internal_map_next_3(BIF_ALIST_3) {
}
}
break;
- } else {
- if (idx < sz) {
- Eterm hdr;
- /* Push next idx in current node */
- WSTACK_PUSH4(stack, node, idx+1, sz, (UWord)ptr);
-
- /* Push first idx in child node */
- node = ptr[idx];
- ptr = hashmap_val(ptr[idx]);
- hdr = *ptr++;
- sz = hashmap_node_size(hdr, &ptr);
- WSTACK_PUSH4(stack, node, 0, sz, (UWord)ptr);
- }
}
-
- /* There are no more element in the hashmap */
- if (WSTACK_ISEMPTY(stack)) {
+ else if (idx < sz) {
+ Eterm hdr;
+ /* Push next idx in current node */
+ WSTACK_PUSH4(stack, node, idx+1, sz, (UWord)ptr);
+
+ /* Continue with first idx in child node */
+ node = ptr[idx];
+ ptr = hashmap_val(ptr[idx]);
+ hdr = *ptr++;
+ sz = hashmap_node_size(hdr, &ptr);
+ idx = 0;
+ }
+ else if (!WSTACK_ISEMPTY(stack)) {
+ ptr = (Eterm*)WSTACK_POP(stack);
+ sz = (Uint)WSTACK_POP(stack);
+ idx = (Uint)WSTACK_POP(stack);
+ node = (Eterm)WSTACK_POP(stack);
+ }
+ else {
+ /* There are no more element in the hashmap */
break;
}
-
}
if (!WSTACK_ISEMPTY(stack)) {
@@ -3846,24 +4010,16 @@ BIF_RETTYPE erts_internal_map_next_3(BIF_ALIST_3) {
res = CONS(hp, path, res); hp += 2;
}
} else {
- if (type == iterator) {
+ if (type == iterator)
*patch_ptr = am_none;
- HRelease(BIF_P, hp + 4 * elems, hp);
- } else {
- HRelease(BIF_P, hp + (2+3) * elems, hp);
- }
+ HRelease(BIF_P, hp_end, hp);
}
BIF_P->fcalls -= 4 * (orig_elems - elems);
DESTROY_WSTACK(stack);
BIF_RET(res);
badarg:
- if (type == iterator) {
- HRelease(BIF_P, hp + 4 * elems, hp);
- } else {
- HRelease(BIF_P, hp + (2+3) * elems, hp);
- }
- BIF_P->fcalls -= 4 * (orig_elems - elems);
+ ASSERT(hp == NULL);
DESTROY_WSTACK(stack);
BIF_ERROR(BIF_P, BADARG);
}
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index d3a023bc07..05d09557e7 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -56,17 +56,15 @@ typedef struct flatmap_s {
/* the head-node is a bitmap or array with an untagged size */
#define hashmap_size(x) (((hashmap_head_t*) hashmap_val(x))->size)
-#define hashmap_make_hash(Key) make_map_hash(Key, 0)
+#define hashmap_make_hash(Key) make_map_hash(Key)
#define hashmap_restore_hash(Lvl, Key) \
- (((Lvl) < 8) ? \
- hashmap_make_hash(Key) >> (4*(Lvl)) : \
- make_map_hash(Key, ((Lvl) >> 3)) >> (4 * ((Lvl) & 7)))
+ (ASSERT(Lvl < 8), \
+ hashmap_make_hash(Key) >> (4*(Lvl)))
#define hashmap_shift_hash(Hx, Lvl, Key) \
- (((++(Lvl)) & 7) ? \
- (Hx) >> 4 : \
- make_map_hash(Key, ((Lvl) >> 3)))
+ (++(Lvl), ASSERT(Lvl <= HAMT_MAX_LEVEL), /* we allow one level too much */\
+ (Hx) >> 4)
/* erl_term.h stuff */
#define flatmap_get_values(x) (((Eterm *)(x)) + sizeof(flatmap_t)/sizeof(Eterm))
@@ -149,7 +147,8 @@ typedef struct hashmap_head_s {
/* erl_map.h stuff */
-#define is_hashmap_header_head(x) ((MAP_HEADER_TYPE(x) & (0x2)))
+#define is_hashmap_header_head(x) (MAP_HEADER_TYPE(x) & (0x2))
+#define is_hashmap_header_node(x) (MAP_HEADER_TYPE(x) == 1)
#define MAKE_MAP_HEADER(Type,Arity,Val) \
(_make_header(((((Uint16)(Val)) << MAP_HEADER_ARITY_SZ) | (Arity)) << MAP_HEADER_TAG_SZ | (Type) , _TAG_HEADER_MAP))
@@ -166,12 +165,21 @@ typedef struct hashmap_head_s {
#define MAP_HEADER_HAMT_NODE_BITMAP(Bmp) \
MAKE_MAP_HEADER(MAP_HEADER_TAG_HAMT_NODE_BITMAP,0x0,Bmp)
+#define MAP_HEADER_HAMT_COLLISION_NODE(Arity) make_arityval(Arity)
+
#define MAP_HEADER_FLATMAP_SZ (sizeof(flatmap_t) / sizeof(Eterm))
#define HAMT_NODE_ARRAY_SZ (17)
#define HAMT_HEAD_ARRAY_SZ (18)
#define HAMT_NODE_BITMAP_SZ(n) (1 + n)
#define HAMT_HEAD_BITMAP_SZ(n) (2 + n)
+#define HAMT_COLLISION_NODE_SZ(n) (1 + n)
+/*
+ * Collision nodes are used when all hash bits have been exhausted.
+ * They are normal tuples of arity 2 or larger. The elements of a collision
+ * node tuple contain key-value cons cells like the other nodes,
+ * but they are sorted in map-key order.
+ */
/* 2 bits maps tag + 4 bits subtag + 2 ignore bits */
#define _HEADER_MAP_SUBTAG_MASK (0xfc)
@@ -185,11 +193,17 @@ typedef struct hashmap_head_s {
#define hashmap_index(hash) (((Uint32)hash) & 0xf)
+#define HAMT_MAX_LEVEL 8
+
/* hashmap heap size:
[one cons cell + one list term in parent node] per key
[one header + one boxed term in parent node] per inner node
[one header + one size word] for root node
Observed average number of nodes per key is about 0.35.
+
+ Amendment: This size estimation does not take collision nodes into account.
+ It should be good enough though, as collision nodes are rare
+ and only make the size smaller compared to unlimited HAMT depth.
*/
#define HASHMAP_WORDS_PER_KEY 3
#define HASHMAP_WORDS_PER_NODE 2
diff --git a/erts/emulator/beam/erl_md5.c b/erts/emulator/beam/erl_md5.c
index f4b6301b5c..2a4e026d9c 100644
--- a/erts/emulator/beam/erl_md5.c
+++ b/erts/emulator/beam/erl_md5.c
@@ -129,10 +129,9 @@ void MD5Init(MD5_CTX* context)
* operation, processing another message block, and updating the
* context.
*/
-void MD5Update (context, input, inputLen)
- MD5_CTX *context; /* context */
- unsigned char *input; /* input block */
- unsigned int inputLen; /* length of input block */
+void MD5Update (MD5_CTX *context,
+ unsigned char *input, /* input block */
+ unsigned int inputLen) /* length of input block */
{
unsigned int i, index, partLen;
@@ -175,9 +174,8 @@ void MD5Update (context, input, inputLen)
* MD5 finalization. Ends an MD5 message-digest operation, writing
the message digest and zeroizing the context.
*/
-void MD5Final (digest, context)
- unsigned char digest[16]; /* message digest */
- MD5_CTX *context; /* context */
+void MD5Final (unsigned char digest[16], /* message digest */
+ MD5_CTX *context) /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
@@ -213,9 +211,7 @@ void MD5Final (digest, context)
/*
* MD5 basic transformation. Transforms state based on block.
*/
-static void MD5Transform (state, block)
- Uint32 state[4];
- unsigned char block[64];
+static void MD5Transform (Uint32 state[4], unsigned char block[64])
{
Uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
@@ -308,10 +304,7 @@ static void MD5Transform (state, block)
* Encodes input (Uint32) into output (unsigned char). Assumes len is
* a multiple of 4.
*/
-static void Encode (output, input, len)
- unsigned char *output;
- Uint32 *input;
- unsigned int len;
+static void Encode (unsigned char *output, Uint32 *input, unsigned int len)
{
unsigned int i, j;
@@ -327,10 +320,7 @@ static void Encode (output, input, len)
* Decodes input (unsigned char) into output (Uint32). Assumes len is
* a multiple of 4.
*/
-static void Decode (output, input, len)
- Uint32 *output;
- unsigned char *input;
- unsigned int len;
+static void Decode (Uint32 *output, unsigned char *input, unsigned int len)
{
unsigned int i, j;
diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c
index 2c7b765520..0c1eef68f0 100644
--- a/erts/emulator/beam/erl_monitor_link.c
+++ b/erts/emulator/beam/erl_monitor_link.c
@@ -703,10 +703,15 @@ erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root,
void *arg,
void *vysp)
{
- void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE,
- sizeof(ErtsMonLnkYieldState));
+ void *tmp_vysp;
Sint reds;
- sys_memcpy(tmp_vysp, tmp_vysp, sizeof(ErtsMonLnkYieldState));
+ if (!vysp)
+ tmp_vysp = NULL;
+ else {
+ tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE,
+ sizeof(ErtsMonLnkYieldState));
+ sys_memcpy(tmp_vysp, tmp_vysp, sizeof(ErtsMonLnkYieldState));
+ }
do {
reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root,
(ErtsMonLnkNodeFunc) func,
@@ -1338,10 +1343,15 @@ erts_debug_link_tree_destroying_foreach(ErtsLink *root,
void *arg,
void *vysp)
{
- void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE,
- sizeof(ErtsMonLnkYieldState));
+ void *tmp_vysp;
Sint reds;
- sys_memcpy(tmp_vysp, vysp, sizeof(ErtsMonLnkYieldState));
+ if (!vysp)
+ tmp_vysp = NULL;
+ else {
+ tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE,
+ sizeof(ErtsMonLnkYieldState));
+ sys_memcpy(tmp_vysp, vysp, sizeof(ErtsMonLnkYieldState));
+ }
do {
reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root,
(ErtsMonLnkNodeFunc) func,
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 086dfa95ad..a9661dc780 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -2922,7 +2922,7 @@ void erts_nif_demonitored(ErtsResource* resource)
ASSERT(resource->type->fn.down);
erts_mtx_lock(&rmp->lock);
- free_me = ((rmon_refc_dec_read(rmp) == 0) & !!rmon_is_dying(rmp));
+ free_me = ((rmon_refc_dec_read(rmp) == 0) && !!rmon_is_dying(rmp));
erts_mtx_unlock(&rmp->lock);
if (free_me)
@@ -5265,7 +5265,7 @@ erts_unload_nif(struct erl_module_nif* lib)
deref_nifmod(lib);
}
-void erl_nif_init()
+void erl_nif_init(void)
{
ERTS_CT_ASSERT((offsetof(ErtsResource,data) % 8)
== ERTS_MAGIC_BIN_BYTES_TO_ALIGN);
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 2bec8ff20e..dac24d0310 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -885,6 +885,18 @@ erts_node_table_info(fmtfn_t to, void *to_arg)
erts_rwmtx_runlock(&erts_node_table_rwmtx);
}
+ErlNode *erts_find_node(Eterm sysname, Uint32 creation)
+{
+ ErlNode *res;
+ ErlNode ne;
+ ne.sysname = sysname;
+ ne.creation = creation;
+
+ erts_rwmtx_rlock(&erts_node_table_rwmtx);
+ res = hash_get(&erts_node_table, (void *) &ne);
+ erts_rwmtx_runlock(&erts_node_table_rwmtx);
+ return res;
+}
ErlNode *erts_find_or_insert_node(Eterm sysname, Uint32 creation, Eterm book)
{
diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h
index c12198a23c..56696586c6 100644
--- a/erts/emulator/beam/erl_node_tables.h
+++ b/erts/emulator/beam/erl_node_tables.h
@@ -255,6 +255,7 @@ void erts_set_dist_entry_not_connected(DistEntry *);
void erts_set_dist_entry_pending(DistEntry *);
void erts_set_dist_entry_connected(DistEntry *, Eterm, Uint64);
ErlNode *erts_find_or_insert_node(Eterm, Uint32, Eterm);
+ErlNode *erts_find_node(Eterm, Uint32);
void erts_schedule_delete_node(ErlNode *);
void erts_set_this_node(Eterm, Uint32);
Uint erts_node_table_size(void);
@@ -282,6 +283,7 @@ ERTS_GLB_INLINE void erts_deref_node_entry__(ErlNode *np, Eterm term, char *file
ERTS_GLB_INLINE erts_aint_t erts_ref_node_entry(ErlNode *np, int min_val, Eterm term);
ERTS_GLB_INLINE void erts_deref_node_entry(ErlNode *np, Eterm term);
#endif
+ERTS_GLB_INLINE erts_aint_t erts_node_refc(ErlNode *np);
ERTS_GLB_INLINE void erts_de_rlock(DistEntry *dep);
ERTS_GLB_INLINE void erts_de_runlock(DistEntry *dep);
ERTS_GLB_INLINE void erts_de_rwlock(DistEntry *dep);
@@ -332,6 +334,12 @@ erts_deref_node_entry(ErlNode *np, Eterm term)
erts_schedule_delete_node(np);
}
+ERTS_GLB_INLINE erts_aint_t
+erts_node_refc(ErlNode *np)
+{
+ return erts_refc_read(&np->refc, 0);
+}
+
#endif
ERTS_GLB_INLINE void
diff --git a/erts/emulator/beam/erl_posix_str.c b/erts/emulator/beam/erl_posix_str.c
index 5b515d6e78..c57c269095 100644
--- a/erts/emulator/beam/erl_posix_str.c
+++ b/erts/emulator/beam/erl_posix_str.c
@@ -47,8 +47,7 @@
*/
char *
-erl_errno_id(error)
- int error; /* Posix error number (as from errno). */
+erl_errno_id(int error /* Posix error number (as from errno). */)
{
switch (error) {
#ifdef E2BIG
diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c
index bb8a422343..18858a21bc 100644
--- a/erts/emulator/beam/erl_printf_term.c
+++ b/erts/emulator/beam/erl_printf_term.c
@@ -722,71 +722,46 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount) {
}
} else {
Uint n, mapval;
+ Eterm* assoc;
+ Eterm key, val;
+
mapval = MAP_HEADER_VAL(*head);
switch (MAP_HEADER_TYPE(*head)) {
case MAP_HEADER_TAG_HAMT_HEAD_ARRAY:
case MAP_HEADER_TAG_HAMT_HEAD_BITMAP:
PRINT_STRING(res, fn, arg, "#{");
WSTACK_PUSH(s, PRT_CLOSE_TUPLE);
- n = hashmap_bitcount(mapval);
- ASSERT(n < 17);
- head += 2;
- if (n > 0) {
- Eterm* assoc;
- Eterm key, val;
- n--;
- if (is_list(head[n])) {
- assoc = list_val(head[n]);
- key = CAR(assoc);
- val = CDR(assoc);
- WSTACK_PUSH5(s, val, PRT_TERM, PRT_ASSOC, key, PRT_TERM);
- } else {
- WSTACK_PUSH(s, head[n]);
- WSTACK_PUSH(s, PRT_TERM);
- }
- while (n--) {
- if (is_list(head[n])) {
- assoc = list_val(head[n]);
- key = CAR(assoc);
- val = CDR(assoc);
- WSTACK_PUSH6(s, PRT_COMMA, val, PRT_TERM, PRT_ASSOC, key, PRT_TERM);
- } else {
- WSTACK_PUSH(s, PRT_COMMA);
- WSTACK_PUSH(s, head[n]);
- WSTACK_PUSH(s, PRT_TERM);
- }
- }
- }
- break;
+ head++;
+ /* fall through */
case MAP_HEADER_TAG_HAMT_NODE_BITMAP:
n = hashmap_bitcount(mapval);
- head++;
- ASSERT(n < 17);
- if (n > 0) {
- Eterm* assoc;
- Eterm key, val;
- n--;
+ ASSERT(0 < n && n < 17);
+ while (1) {
if (is_list(head[n])) {
assoc = list_val(head[n]);
key = CAR(assoc);
val = CDR(assoc);
WSTACK_PUSH5(s, val, PRT_TERM, PRT_ASSOC, key, PRT_TERM);
- } else {
- WSTACK_PUSH(s, head[n]);
- WSTACK_PUSH(s, PRT_TERM);
}
- while (n--) {
- if (is_list(head[n])) {
- assoc = list_val(head[n]);
+ else if (is_tuple(head[n])) { /* collision node */
+ Eterm *tpl = tuple_val(head[n]);
+ Uint arity = arityval(tpl[0]);
+ ASSERT(arity >= 2);
+ while (1) {
+ assoc = list_val(tpl[arity]);
key = CAR(assoc);
val = CDR(assoc);
- WSTACK_PUSH6(s, PRT_COMMA, val, PRT_TERM, PRT_ASSOC, key, PRT_TERM);
- } else {
+ WSTACK_PUSH5(s, val, PRT_TERM, PRT_ASSOC, key, PRT_TERM);
+ if (--arity == 0)
+ break;
WSTACK_PUSH(s, PRT_COMMA);
- WSTACK_PUSH(s, head[n]);
- WSTACK_PUSH(s, PRT_TERM);
}
+ } else {
+ WSTACK_PUSH2(s, head[n], PRT_TERM);
}
+ if (--n == 0)
+ break;
+ WSTACK_PUSH(s, PRT_COMMA);
}
break;
}
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index e444a4cdca..ee1d345fb3 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -5626,6 +5626,7 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
mdp->ref, c_p->common.id,
NIL, NIL, THE_NON_VALUE);
amdp->origin.flags = ERTS_ML_STATE_ALIAS_UNALIAS;
+ omon->flags &= ~ERTS_ML_STATE_ALIAS_MASK;
erts_monitor_tree_replace(&ERTS_P_MONITORS(c_p),
omon,
&amdp->origin);
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index d4502a8b1a..7a89df49e0 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -7397,7 +7397,7 @@ static ERTS_INLINE int
have_dirty_work(void)
{
return !(ERTS_EMPTY_RUNQ(ERTS_DIRTY_CPU_RUNQ)
- | ERTS_EMPTY_RUNQ(ERTS_DIRTY_IO_RUNQ));
+ || ERTS_EMPTY_RUNQ(ERTS_DIRTY_IO_RUNQ));
}
#define ERTS_MSB_NONE_PRIO_BIT PORT_BIT
@@ -8781,7 +8781,7 @@ erts_start_schedulers(void)
{
ethr_tid tid;
int res = 0;
- char name[32];
+ char name[ETHR_THR_NAME_MAX + 1];
ethr_thr_opts opts = ETHR_THR_OPTS_DEFAULT_INITER;
int ix;
@@ -8791,7 +8791,7 @@ erts_start_schedulers(void)
if (erts_runq_supervision_interval) {
opts.suggested_stack_size = 16;
- erts_snprintf(opts.name, sizeof(name), "runq_supervisor");
+ erts_snprintf(opts.name, sizeof(name), "erts_runq_sup");
erts_atomic_init_nob(&runq_supervisor_sleeping, 0);
if (0 != ethr_event_init(&runq_supervision_event))
erts_exit(ERTS_ABORT_EXIT, "Failed to create run-queue supervision event\n");
@@ -8812,7 +8812,7 @@ erts_start_schedulers(void)
for (ix = 0; ix < erts_no_schedulers; ix++) {
ErtsSchedulerData *esdp = ERTS_SCHEDULER_IX(ix);
ASSERT(ix == esdp->no - 1);
- erts_snprintf(opts.name, sizeof(name), "%lu_scheduler", ix + 1);
+ erts_snprintf(opts.name, sizeof(name), "erts_sched_%d", ix + 1);
res = ethr_thr_create(&esdp->tid, sched_thread_func, (void*)esdp, &opts);
if (res != 0) {
erts_exit(ERTS_ABORT_EXIT, "Failed to create scheduler thread %d, error = %d\n", ix, res);
@@ -8826,7 +8826,7 @@ erts_start_schedulers(void)
{
for (ix = 0; ix < erts_no_dirty_cpu_schedulers; ix++) {
ErtsSchedulerData *esdp = ERTS_DIRTY_CPU_SCHEDULER_IX(ix);
- erts_snprintf(opts.name, sizeof(name), "%d_dirty_cpu_scheduler", ix + 1);
+ erts_snprintf(opts.name, sizeof(name), "erts_dcpus_%d", ix + 1);
opts.suggested_stack_size = erts_dcpu_sched_thread_suggested_stack_size;
res = ethr_thr_create(&esdp->tid,sched_dirty_cpu_thread_func,(void*)esdp,&opts);
if (res != 0)
@@ -8834,7 +8834,7 @@ erts_start_schedulers(void)
}
for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) {
ErtsSchedulerData *esdp = ERTS_DIRTY_IO_SCHEDULER_IX(ix);
- erts_snprintf(opts.name, sizeof(name), "%d_dirty_io_scheduler", ix + 1);
+ erts_snprintf(opts.name, sizeof(name), "erts_dios_%d", ix + 1);
opts.suggested_stack_size = erts_dio_sched_thread_suggested_stack_size;
res = ethr_thr_create(&esdp->tid,sched_dirty_io_thread_func,(void*)esdp,&opts);
if (res != 0)
@@ -8845,7 +8845,7 @@ erts_start_schedulers(void)
ix = 0;
while (ix < erts_no_aux_work_threads) {
int id = ix == 0 ? 1 : ix + 1 - (int) erts_no_schedulers;
- erts_snprintf(opts.name, sizeof(name), "%d_aux", id);
+ erts_snprintf(opts.name, sizeof(name), "erts_aux_%d", id);
res = ethr_thr_create(&tid, aux_thread, (void *) (Sint) ix, &opts);
if (res != 0)
@@ -8872,7 +8872,7 @@ erts_start_schedulers(void)
bpt->blocked = 0;
bpt->id = ix;
- erts_snprintf(opts.name, sizeof(name), "%d_poller", ix);
+ erts_snprintf(opts.name, sizeof(name), "erts_poll_%d", ix);
res = ethr_thr_create(&tid, poll_thread, (void*) bpt, &opts);
if (res != 0)
diff --git a/erts/emulator/beam/erl_process_lock.h b/erts/emulator/beam/erl_process_lock.h
index 3c8428c5b9..76e8616280 100644
--- a/erts/emulator/beam/erl_process_lock.h
+++ b/erts/emulator/beam/erl_process_lock.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2007-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2007-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -991,6 +991,7 @@ erts_proc_lock_wait_until_released(Process *p, ErtsProcLocks locks)
#if ERTS_PROC_LOCK_OWN_IMPL
#if !ERTS_PROC_LOCK_ATOMIC_IMPL
Uint32 was_locked;
+ erts_pix_lock_t *pix_lck = ERTS_PID2PIXLOCK(p->common.id);
erts_pix_lock(pix_lck);
was_locked = (ERTS_PROC_LOCK_FLGS_READ_(&p->lock) & locks);
erts_pix_unlock(pix_lck);
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index cff38badf7..03211a6acd 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -331,7 +331,7 @@ _ET_DECLARE_CHECKED(Uint,header_arity,Eterm)
#define is_sane_arity_value(x) ((((x) & _TAG_HEADER_MASK) == _TAG_HEADER_ARITYVAL) && \
(((x) >> _HEADER_ARITY_OFFS) <= MAX_ARITYVAL))
#define is_not_arity_value(x) (!is_arity_value((x)))
-#define _unchecked_arityval(x) _unchecked_header_arity((x))
+#define _unchecked_arityval(x) ((x) >> _HEADER_ARITY_OFFS)
_ET_DECLARE_CHECKED(Uint,arityval,Eterm)
#define arityval(x) _ET_APPLY(arityval,(x))
@@ -1268,15 +1268,12 @@ _ET_DECLARE_CHECKED(struct erl_node_*,external_ref_node,Eterm)
#define MAP_SZ(sz) (MAP_HEADER_FLATMAP_SZ + 2*sz + 1)
-#define MAP0_SZ MAP_SZ(0)
#define MAP1_SZ MAP_SZ(1)
#define MAP2_SZ MAP_SZ(2)
#define MAP3_SZ MAP_SZ(3)
#define MAP4_SZ MAP_SZ(4)
#define MAP5_SZ MAP_SZ(5)
-#define MAP0(hp) \
- (MAP_HEADER(hp, 0, TUPLE0(hp+MAP_HEADER_FLATMAP_SZ)), \
- make_flatmap(hp))
+
#define MAP1(hp, k1, v1) \
(MAP_HEADER(hp, 1, TUPLE1(hp+1+MAP_HEADER_FLATMAP_SZ, k1)), \
(hp)[MAP_HEADER_FLATMAP_SZ+0] = v1, \
diff --git a/erts/emulator/beam/erl_term_hashing.c b/erts/emulator/beam/erl_term_hashing.c
index 52c36503ee..848757c2f2 100644
--- a/erts/emulator/beam/erl_term_hashing.c
+++ b/erts/emulator/beam/erl_term_hashing.c
@@ -1141,7 +1141,18 @@ make_hash2_helper(Eterm term_param, const int can_trap, Eterm* state_mref_write_
}
else {
ASSERT(is_boxed(*ctx.ptr));
- ESTACK_PUSH(s, *ctx.ptr);
+ if (is_tuple(*ctx.ptr)) { /* collision node */
+ Eterm *coll_ptr = tuple_val(*ctx.ptr);
+ Uint n = arityval(*coll_ptr);
+ ASSERT(n >= 2);
+ coll_ptr++;
+ for (; n; n--, coll_ptr++) {
+ Eterm* cons = list_val(*coll_ptr);
+ ESTACK_PUSH3(s, HASH_MAP_PAIR, CDR(cons), CAR(cons));
+ }
+ }
+ else
+ ESTACK_PUSH(s, *ctx.ptr);
}
ctx.i--; ctx.ptr++;
TRAP_LOCATION(map_subtag);
@@ -1543,12 +1554,10 @@ trapping_make_hash2(Eterm term, Eterm* state_mref_write_back, Process* p)
* with a new ErlNode struct, externals from that node will hash different than
* before.
*
- * One IMPORTANT property must hold (for hamt).
- * EVERY BIT of the term that is significant for equality (see EQ)
- * MUST BE USED AS INPUT FOR THE HASH. Two different terms must always have a
- * chance of hashing different when salted.
- *
- * This is why we cannot use cached hash values for atoms for example.
+ * The property "EVERY BIT of the term that is significant for equality
+ * MUST BE USED AS INPUT FOR THE HASH" is nice but no longer crucial for the
+ * hashmap implementation that now uses collision nodes at the bottom of
+ * the HAMT when all hash bits are exhausted.
*
*/
@@ -1716,6 +1725,8 @@ make_internal_hash(Eterm term, Uint32 salt)
}
else {
ASSERT(is_boxed(*ptr));
+ /* no special treatment of collision nodes needed,
+ hash them as the tuples they are */
ESTACK_PUSH(s, *ptr);
}
i--; ptr++;
@@ -1951,15 +1962,43 @@ make_internal_hash(Eterm term, Uint32 salt)
}
-/* Term hash function for maps, with a separate depth parameter */
-Uint32 make_map_hash(Eterm key, int depth) {
- Uint32 hash = 0;
-
- if (depth > 0) {
- UINT32_HASH_2(depth, 1, HCONST_22);
+#ifdef DBG_HASHMAP_COLLISION_BONANZA
+Uint32 erts_dbg_hashmap_collision_bonanza(Uint32 hash, Eterm key)
+{
+/*{
+ static Uint32 hashvec[7] = {
+ 0x02345678,
+ 0x12345678,
+ 0xe2345678,
+ 0xf2345678,
+ 0x12abcdef,
+ 0x13abcdef,
+ 0xcafebabe
+ };
+ hash = hashvec[hash % (sizeof(hashvec) / sizeof(hashvec[0]))];
+ }*/
+ const Uint32 bad_hash = (hash & 0x12482481) * 1442968193;
+ const Uint32 bad_bits = hash % 67;
+ if (bad_bits < 32) {
+ /* Mix in a number of high good bits to get "randomly" close
+ to the collision nodes */
+ const Uint32 bad_mask = (1 << bad_bits) - 1;
+ return (hash & ~bad_mask) | (bad_hash & bad_mask);
}
+ return bad_hash;
+}
+#endif
- return make_internal_hash(key, hash);
+/* Term hash function for hashmaps */
+Uint32 make_map_hash(Eterm key) {
+ Uint32 hash;
+
+ hash = make_internal_hash(key, 0);
+
+#ifdef DBG_HASHMAP_COLLISION_BONANZA
+ hash = erts_dbg_hashmap_collision_bonanza(hash, key);
+#endif
+ return hash;
}
#undef CONST_HASH
diff --git a/erts/emulator/beam/erl_term_hashing.h b/erts/emulator/beam/erl_term_hashing.h
index ec4a49359d..8a898b7c52 100644
--- a/erts/emulator/beam/erl_term_hashing.h
+++ b/erts/emulator/beam/erl_term_hashing.h
@@ -53,7 +53,13 @@ Uint32 make_hash2(Eterm);
Uint32 trapping_make_hash2(Eterm, Eterm*, struct process*);
Uint32 make_hash(Eterm);
Uint32 make_internal_hash(Eterm, Uint32 salt);
-Uint32 make_map_hash(Eterm key, int level);
+#ifdef DEBUG
+# define DBG_HASHMAP_COLLISION_BONANZA
+#endif
+#ifdef DBG_HASHMAP_COLLISION_BONANZA
+Uint32 erts_dbg_hashmap_collision_bonanza(Uint32 hash, Eterm key);
+#endif
+Uint32 make_map_hash(Eterm key);
void erts_block_hash_init(ErtsBlockHashState *state,
const byte *ptr,
Uint len,
diff --git a/erts/emulator/beam/erl_threads.h b/erts/emulator/beam/erl_threads.h
index d3639e1135..ec43772bca 100644
--- a/erts/emulator/beam/erl_threads.h
+++ b/erts/emulator/beam/erl_threads.h
@@ -430,6 +430,7 @@ ERTS_GLB_INLINE void erts_thr_exit(void *res);
ERTS_GLB_INLINE void erts_thr_install_exit_handler(void (*exit_handler)(void));
ERTS_GLB_INLINE erts_tid_t erts_thr_self(void);
ERTS_GLB_INLINE int erts_thr_getname(erts_tid_t tid, char *buf, size_t len);
+ERTS_GLB_INLINE void erts_thr_setname(char *buf);
ERTS_GLB_INLINE int erts_equal_tids(erts_tid_t x, erts_tid_t y);
ERTS_GLB_INLINE void erts_mtx_init(erts_mtx_t *mtx,
const char *name,
@@ -1623,6 +1624,13 @@ erts_thr_getname(erts_tid_t tid, char *buf, size_t len)
return ethr_getname(tid, buf, len);
}
+ERTS_GLB_INLINE void
+erts_thr_setname(char *buf)
+{
+ if (strlen(buf) > ETHR_THR_NAME_MAX)
+ erts_thr_fatal_error(EINVAL, "too long thread name");
+ ethr_setname(buf);
+}
ERTS_GLB_INLINE int
erts_equal_tids(erts_tid_t x, erts_tid_t y)
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 82d4cf728c..2dd6c99d4c 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2022. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -2473,7 +2473,7 @@ init_sys_msg_dispatcher(void)
{
erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
thr_opts.detached = 1;
- thr_opts.name = "sys_msg_dispatcher";
+ thr_opts.name = "erts_smsg_disp";
init_smq_element_alloc();
sys_message_queue = NULL;
sys_message_queue_end = NULL;
@@ -3079,7 +3079,7 @@ erts_tracer_update(ErtsTracer *tracer, const ErtsTracer new_tracer)
}
}
-static void init_tracer_nif()
+static void init_tracer_nif(void)
{
erts_rwmtx_opt_t rwmtx_opt = ERTS_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_RWMTX_TYPE_EXTREMELY_FREQUENT_READ;
@@ -3092,7 +3092,7 @@ static void init_tracer_nif()
}
-int erts_tracer_nif_clear()
+int erts_tracer_nif_clear(void)
{
erts_rwmtx_rlock(&tracer_mtx);
diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h
index 3c7a6054c5..6d5b7c6e1b 100644
--- a/erts/emulator/beam/erl_vm.h
+++ b/erts/emulator/beam/erl_vm.h
@@ -323,7 +323,7 @@ extern void** beam_ops;
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE
-int erts_cp_size()
+int erts_cp_size(void)
{
if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
return 1;
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index a380454699..081ce23e49 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -3116,7 +3116,6 @@ dec_pid(ErtsDistExternal *edep, ErtsHeapFactory* factory, const byte* ep,
#define ENC_BIN_COPY ((Eterm) 3)
#define ENC_MAP_PAIR ((Eterm) 4)
#define ENC_HASHMAP_NODE ((Eterm) 5)
-#define ENC_STORE_MAP_ELEMENT ((Eterm) 6)
#define ENC_START_SORTING_MAP ((Eterm) 7)
#define ENC_CONTINUE_SORTING_MAP ((Eterm) 8)
#define ENC_PUSH_SORTED_MAP ((Eterm) 9)
@@ -3315,18 +3314,32 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
case ENC_HASHMAP_NODE:
if (is_list(obj)) { /* leaf node [K|V] */
ptr = list_val(obj);
+ if (dflags & DFLAG_DETERMINISTIC) {
+ *next_map_element++ = CAR(ptr);
+ *next_map_element++ = CDR(ptr);
+ goto outer_loop;
+ }
WSTACK_PUSH2(s, ENC_TERM, CDR(ptr));
obj = CAR(ptr);
}
- break;
- case ENC_STORE_MAP_ELEMENT: /* option `deterministic` */
- if (is_list(obj)) { /* leaf node [K|V] */
- ptr = list_val(obj);
- *next_map_element++ = CAR(ptr);
- *next_map_element++ = CDR(ptr);
+ else if (is_tuple(obj)) { /* collision node */
+ Uint tpl_sz;
+ ptr = tuple_val(obj);
+ tpl_sz = arityval(*ptr);
+ ASSERT(tpl_sz >= 2);
+ ptr++;
+ WSTACK_RESERVE(s, tpl_sz * 2);
+ while(tpl_sz--) {
+ ASSERT(is_list(*ptr));
+ WSTACK_FAST_PUSH(s, ENC_HASHMAP_NODE);
+ WSTACK_FAST_PUSH(s, *ptr++);
+ }
goto outer_loop;
- }
- break;
+ }
+ else
+ ASSERT((*boxed_val(obj) & _HEADER_MAP_SUBTAG_MASK)
+ == HAMT_SUBTAG_NODE_BITMAP);
+ break;
case ENC_START_SORTING_MAP: /* option `deterministic` */
{
long num_reductions = r;
@@ -3654,7 +3667,6 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
} else {
Eterm hdr;
Uint node_sz;
- Eterm node_processor;
ptr = boxed_val(obj);
hdr = *ptr;
ASSERT(is_header(hdr));
@@ -3695,17 +3707,14 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
node_sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
ASSERT(node_sz < 17);
break;
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header\r\n");
- }
-
+ default:
+ erts_exit(ERTS_ERROR_EXIT, "bad header\r\n");
+ }
ptr++;
- node_processor = (dflags & DFLAG_DETERMINISTIC) ?
- ENC_STORE_MAP_ELEMENT : ENC_HASHMAP_NODE;
WSTACK_RESERVE(s, node_sz*2);
while(node_sz--) {
- WSTACK_FAST_PUSH(s, node_processor);
- WSTACK_FAST_PUSH(s, *ptr++);
+ WSTACK_FAST_PUSH(s, ENC_HASHMAP_NODE);
+ WSTACK_FAST_PUSH(s, *ptr++);
}
}
break;
@@ -5459,8 +5468,8 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
node_sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
ASSERT(node_sz < 17);
break;
- default:
- erts_exit(ERTS_ERROR_EXIT, "bad header\r\n");
+ default:
+ erts_exit(ERTS_ERROR_EXIT, "bad header\r\n");
}
ptr++;
diff --git a/erts/emulator/beam/hash.c b/erts/emulator/beam/hash.c
index 434ba25098..5c8b43e6e2 100644
--- a/erts/emulator/beam/hash.c
+++ b/erts/emulator/beam/hash.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,6 +64,7 @@ void hash_get_info(HashInfo *hi, Hash *h)
}
}
ASSERT(objects == h->nobjs);
+ (void)objects;
hi->name = h->name;
hi->size = hash_get_slots(h);
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index b024782073..a79bce3d77 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2022. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -3126,8 +3126,7 @@ void erts_lcnt_update_port_locks(int enable) {
* Parameters:
* bufsiz - The (maximum) size of the line buffer.
*/
-LineBuf *allocate_linebuf(bufsiz)
-int bufsiz;
+LineBuf *allocate_linebuf(int bufsiz)
{
int ovsiz = (bufsiz < LINEBUF_INITIAL) ? bufsiz : LINEBUF_INITIAL;
LineBuf *lb = (LineBuf *) erts_alloc(ERTS_ALC_T_LINEBUF,
diff --git a/erts/emulator/beam/jit/arm/instr_map.cpp b/erts/emulator/beam/jit/arm/instr_map.cpp
index b751436881..8d7ad6f45f 100644
--- a/erts/emulator/beam/jit/arm/instr_map.cpp
+++ b/erts/emulator/beam/jit/arm/instr_map.cpp
@@ -30,13 +30,10 @@ extern "C"
}
static const Uint32 INTERNAL_HASH_SALT = 3432918353;
-static const Uint32 HCONST_22 = 0x98C475E6UL;
static const Uint32 HCONST = 0x9E3779B9;
-/* ARG3 = incoming hash
- * ARG6 = lower 32
+/* ARG6 = lower 32
* ARG7 = upper 32
- * ARG8 = type constant
*
* Helper function for calculating the internal hash of keys before looking
* them up in a map.
@@ -50,6 +47,9 @@ void BeamGlobalAssembler::emit_internal_hash_helper() {
a64::Gp hash = ARG3.w(), lower = ARG6.w(), upper = ARG7.w(),
constant = ARG8.w();
+ mov_imm(hash, INTERNAL_HASH_SALT);
+ mov_imm(constant, HCONST);
+
a.add(lower, lower, constant);
a.add(upper, upper, constant);
@@ -82,6 +82,24 @@ void BeamGlobalAssembler::emit_internal_hash_helper() {
}
#endif
+#ifdef DBG_HASHMAP_COLLISION_BONANZA
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ a.stp(ARG1, ARG2, TMP_MEM1q);
+ a.str(ARG4, TMP_MEM3q);
+
+ a.mov(ARG1, ARG3);
+ runtime_call<2>(erts_dbg_hashmap_collision_bonanza);
+ a.mov(ARG3, ARG1);
+
+ a.ldp(ARG1, ARG2, TMP_MEM1q);
+ a.ldr(ARG4, TMP_MEM3q);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+#endif
+
a.ret(a64::x30);
}
@@ -95,7 +113,7 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
Label node_loop = a.newLabel();
arm::Gp node = ARG1, key = ARG2, key_hash = ARG3, header_val = ARG4,
- depth = TMP4, index = TMP5;
+ depth = TMP5, index = TMP6;
const int header_shift =
(_HEADER_ARITY_OFFS + MAP_HEADER_TAG_SZ + MAP_HEADER_ARITY_SZ);
@@ -107,8 +125,9 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
a.bind(node_loop);
{
- Label fail = a.newLabel(), leaf_node = a.newLabel(),
- skip_index_adjustment = a.newLabel(), update_hash = a.newLabel();
+ Label done = a.newLabel(), leaf_node = a.newLabel(),
+ skip_index_adjustment = a.newLabel(),
+ collision_node = a.newLabel();
/* Find out which child we should follow, and shift the hash for the
* next round. */
@@ -128,7 +147,7 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
* Note that we jump directly to the return sequence as ZF is clear
* at this point. */
a.lsr(TMP1, header_val, index);
- a.tbz(TMP1, imm(0), fail);
+ a.tbz(TMP1, imm(0), done);
/* The actual offset of our entry is the number of bits set (in
* essence "entries present") before our index in the bitmap. Clear
@@ -152,11 +171,11 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
* word. */
a.ldr(header_val, arm::Mem(node).post(sizeof(Eterm)));
- /* After 8 nodes we've run out of the 32 bits we started with, so we
- * need to update the hash to keep going. */
- a.tst(depth, imm(0x7));
- a.b_eq(update_hash);
- a.b(node_loop);
+ /* After 8 nodes we've run out of the 32 bits we started with
+ * and we end up in a collision node. */
+ a.cmp(depth, imm(HAMT_MAX_LEVEL));
+ a.b_ne(node_loop);
+ a.b(collision_node);
a.bind(leaf_node);
{
@@ -166,36 +185,33 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
a.cmp(TMP1, key);
/* See comment at the jump. */
- a.bind(fail);
+ a.bind(done);
a.ret(a64::x30);
}
- /* After 8 nodes we've run out of the 32 bits we started with, so we
- * must calculate a new hash to continue.
- *
- * This is a manual expansion `make_map_hash` from utils.c, and all
- * changes to that function must be mirrored here. */
- a.bind(update_hash);
+ /* A collision node is a tuple of leafs where we do linear search.*/
+ a.bind(collision_node);
{
- emit_enter_runtime_frame();
+ Label linear_loop = a.newLabel();
+
+ a.lsr(TMP1, header_val, imm(_HEADER_ARITY_OFFS - 3));
- /* NOTE: ARG3 (key_hash) is always 0 at this point. */
- a.lsr(ARG6, depth, imm(3));
- mov_imm(ARG7, 1);
- mov_imm(ARG8, HCONST_22);
- a.bl(labels[internal_hash_helper]);
+ a.bind(linear_loop);
+ {
+ a.sub(TMP1, TMP1, imm(8));
- mov_imm(TMP1, INTERNAL_HASH_SALT);
- a.eor(ARG3, ARG3, TMP1);
+ a.ldr(TMP2, arm::Mem(node, TMP1));
- a.mov(ARG6.w(), key.w());
- a.lsr(ARG7, key, imm(32));
- mov_imm(ARG8, HCONST);
- a.bl(labels[internal_hash_helper]);
+ emit_untag_ptr(TMP2, TMP2);
+ a.ldp(TMP3, TMP4, arm::Mem(TMP2));
+ a.cmp(key, TMP3);
+ a.csel(ARG1, node, TMP4, imm(arm::CondCode::kNE));
+ a.b_eq(done);
- emit_leave_runtime_frame();
+ a.cbnz(TMP1, linear_loop);
+ }
- a.b(node_loop);
+ a.ret(a64::x30);
}
}
}
@@ -362,10 +378,8 @@ void BeamGlobalAssembler::emit_i_get_map_element_shared() {
emit_enter_runtime_frame();
/* Calculate the internal hash of ARG2 before diving into the HAMT. */
- mov_imm(ARG3, INTERNAL_HASH_SALT);
a.mov(ARG6.w(), ARG2.w());
a.lsr(ARG7, ARG2, imm(32));
- mov_imm(ARG8, HCONST);
a.bl(labels[internal_hash_helper]);
emit_leave_runtime_frame();
diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab
index 3389ec4459..6d27a18c2d 100644
--- a/erts/emulator/beam/jit/arm/ops.tab
+++ b/erts/emulator/beam/jit/arm/ops.tab
@@ -1042,6 +1042,10 @@ bs_skip_utf16 Fail=f Ms=xy u Flags=u => skip_utf16(Fail, Ms, Flags)
i_bs_get_utf16 S f t d
i_bs_skip_utf16 S f t
+bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst | equal(Ms, Dst) =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags x |
+ i_bs_validate_unicode_retract Fail x Ms |
+ move x Dst
bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst=d =>
bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst |
i_bs_validate_unicode_retract Fail Dst Ms
diff --git a/erts/emulator/beam/jit/beam_jit_common.cpp b/erts/emulator/beam/jit/beam_jit_common.cpp
index a0bb07ce56..3200f75407 100644
--- a/erts/emulator/beam/jit/beam_jit_common.cpp
+++ b/erts/emulator/beam/jit/beam_jit_common.cpp
@@ -369,10 +369,11 @@ void BeamModuleAssembler::register_metadata(const BeamCodeHeader *header) {
ranges.reserve(functions.size() + 2);
ASSERT((ErtsCodePtr)getBaseAddress() == (ErtsCodePtr)header);
+ ASSERT(functions.size() == header->num_functions);
/* Push info about the header */
ranges.push_back({.start = (ErtsCodePtr)getBaseAddress(),
- .stop = getCode(functions[0]),
+ .stop = (ErtsCodePtr)&header->functions[functions.size()],
.name = module_name + "::codeHeader"});
for (unsigned i = 0; i < functions.size(); i++) {
diff --git a/erts/emulator/beam/jit/beam_jit_main.cpp b/erts/emulator/beam/jit/beam_jit_main.cpp
index 7cd8dbf2aa..0cd732039f 100644
--- a/erts/emulator/beam/jit/beam_jit_main.cpp
+++ b/erts/emulator/beam/jit/beam_jit_main.cpp
@@ -421,9 +421,9 @@ extern "C"
/* Issues full memory/instruction barriers on all threads for us. */
sys_icache_invalidate((char *)address, size);
#elif defined(__aarch64__) && defined(__GNUC__) && \
- defined(ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION) && \
- defined(ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION) && \
- defined(ERTS_THR_INSTRUCTION_BARRIER)
+ defined(ERTS_THR_INSTRUCTION_BARRIER) && \
+ ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION && \
+ ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION
/* Note that we do not issue any barriers here, whether instruction or
* memory. This is on purpose as we must issue those on all schedulers
* and not just the calling thread, and the chances of us forgetting to
diff --git a/erts/emulator/beam/jit/beam_jit_metadata.cpp b/erts/emulator/beam/jit/beam_jit_metadata.cpp
index 780fd97c97..10e82fdf37 100644
--- a/erts/emulator/beam/jit/beam_jit_metadata.cpp
+++ b/erts/emulator/beam/jit/beam_jit_metadata.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/beam/jit/x86/instr_map.cpp b/erts/emulator/beam/jit/x86/instr_map.cpp
index 679b2a6609..5f89077ba6 100644
--- a/erts/emulator/beam/jit/x86/instr_map.cpp
+++ b/erts/emulator/beam/jit/x86/instr_map.cpp
@@ -30,13 +30,11 @@ extern "C"
}
static const Uint32 INTERNAL_HASH_SALT = 3432918353;
-static const Uint32 HCONST_22 = 0x98C475E6UL;
static const Uint32 HCONST = 0x9E3779B9;
-/* ARG3 = incoming hash
+/*
* ARG4 = lower 32
* ARG5 = upper 32
- * ARG6 = type constant
*
* Helper function for calculating the internal hash of keys before looking
* them up in a map.
@@ -47,15 +45,16 @@ static const Uint32 HCONST = 0x9E3779B9;
*
* Result is returned in ARG3. */
void BeamGlobalAssembler::emit_internal_hash_helper() {
- x86::Gp hash = ARG3d, lower = ARG4d, upper = ARG5d, constant = ARG6d;
+ x86::Gp hash = ARG3d, lower = ARG4d, upper = ARG5d;
- a.add(lower, constant);
- a.add(upper, constant);
+ a.mov(hash, imm(INTERNAL_HASH_SALT));
+ a.add(lower, imm(HCONST));
+ a.add(upper, imm(HCONST));
#if defined(ERL_INTERNAL_HASH_CRC32C)
- a.mov(constant, hash);
+ a.mov(ARG6d, hash);
a.crc32(hash, lower);
- a.add(hash, constant);
+ a.add(hash, ARG6d);
a.crc32(hash, upper);
#else
using rounds =
@@ -88,6 +87,23 @@ void BeamGlobalAssembler::emit_internal_hash_helper() {
}
#endif
+#ifdef DBG_HASHMAP_COLLISION_BONANZA
+ a.mov(TMP_MEM1q, ARG1);
+ a.mov(TMP_MEM2q, ARG2);
+ a.mov(TMP_MEM3q, RET);
+
+ a.mov(ARG1, ARG3);
+ emit_enter_runtime();
+ runtime_call<2>(erts_dbg_hashmap_collision_bonanza);
+ emit_leave_runtime();
+
+ a.mov(ARG3d, RETd);
+
+ a.mov(ARG1, TMP_MEM1q);
+ a.mov(ARG2, TMP_MEM2q);
+ a.mov(RET, TMP_MEM3q);
+#endif
+
a.ret();
}
@@ -109,8 +125,9 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
a.bind(node_loop);
{
- Label fail = a.newLabel(), leaf_node = a.newLabel(),
- skip_index_adjustment = a.newLabel(), update_hash = a.newLabel();
+ Label done = a.newLabel(), leaf_node = a.newLabel(),
+ skip_index_adjustment = a.newLabel(),
+ collision_node = a.newLabel();
/* Find out which child we should follow, and shift the hash for the
* next round. */
@@ -131,7 +148,7 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
* Note that we jump directly to a `RET` instruction, as `BT` only
* affects CF, and ZF ("not found") is clear at this point. */
a.bt(header_val, index);
- a.short_().jnc(fail);
+ a.short_().jnc(done);
/* The actual offset of our entry is the number of bits set (in
* essence "entries present") before our index in the bitmap. */
@@ -154,11 +171,11 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
/* Nope, we have to search another node. */
a.mov(header_val, emit_boxed_val(node, 0, sizeof(Uint32)));
- /* After 8 nodes we've run out of the 32 bits we started with, so we
- * need to update the hash to keep going. */
- a.test(depth, imm(0x7));
- a.short_().jz(update_hash);
- a.short_().jmp(node_loop);
+ /* After 8 nodes we've run out of the 32 bits we started with
+ * and we end up in a collision node. */
+ a.test(depth, imm(HAMT_MAX_LEVEL - 1));
+ a.short_().jnz(node_loop);
+ a.short_().jmp(collision_node);
a.bind(leaf_node);
{
@@ -168,36 +185,33 @@ void BeamGlobalAssembler::emit_hashmap_get_element() {
a.mov(RET, getCDRRef(node));
/* See comment at the jump. */
- a.bind(fail);
+ a.bind(done);
a.ret();
}
- /* After 8 nodes we've run out of the 32 bits we started with, so we
- * must calculate a new hash to continue.
- *
- * This is a manual expansion `make_map_hash` from utils.c, and all
- * changes to that function must be mirrored here. */
- a.bind(update_hash);
+ /* A collision node is a tuple of leafs where we do linear search.*/
+ a.bind(collision_node);
{
- a.mov(TMP_MEM1d, depth);
+ Label linear_loop = a.newLabel();
- /* NOTE: ARG3d is always 0 at this point. */
- a.mov(ARG4d, depth);
- a.shr(ARG4d, imm(3));
- mov_imm(ARG5d, 1);
- a.mov(ARG6d, imm(HCONST_22));
- a.call(labels[internal_hash_helper]);
+ a.shr(header_val, imm(_HEADER_ARITY_OFFS));
+ a.lea(ARG6d, x86::qword_ptr(header_val, -1));
- a.xor_(ARG3d, imm(INTERNAL_HASH_SALT));
- a.mov(ARG4d, key.r32());
- a.mov(ARG5, key);
- a.shr(ARG5, imm(32));
- a.mov(ARG6d, imm(HCONST));
- a.call(labels[internal_hash_helper]);
+ a.bind(linear_loop);
+ {
+ a.mov(ARG3,
+ x86::qword_ptr(node, ARG6, 3, 8 - TAG_PRIMARY_BOXED));
- a.mov(depth, TMP_MEM1d);
+ emit_ptr_val(ARG3, ARG3);
+ a.cmp(key, getCARRef(ARG3));
+ a.mov(RET, getCDRRef(ARG3));
+ a.short_().jz(done);
- a.jmp(node_loop);
+ a.dec(ARG6d);
+ a.short_().jns(linear_loop);
+ }
+
+ a.ret();
}
}
}
@@ -381,8 +395,6 @@ void BeamGlobalAssembler::emit_i_get_map_element_shared() {
a.shr(ARG5, imm(32));
a.mov(ARG4d, ARG2d);
- a.mov(ARG3d, imm(INTERNAL_HASH_SALT));
- a.mov(ARG6d, imm(HCONST));
a.call(labels[internal_hash_helper]);
emit_hashmap_get_element();
diff --git a/erts/emulator/beam/jit/x86/ops.tab b/erts/emulator/beam/jit/x86/ops.tab
index 307c3d057e..ef57021d83 100644
--- a/erts/emulator/beam/jit/x86/ops.tab
+++ b/erts/emulator/beam/jit/x86/ops.tab
@@ -1000,6 +1000,11 @@ bs_skip_utf16 Fail=f Ms=xy u Flags=u => skip_utf16(Fail, Ms, Flags)
i_bs_get_utf16 S f t d
i_bs_skip_utf16 S f t
+bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst | equal(Ms, Dst) =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags x |
+ i_bs_validate_unicode_retract Fail x Ms |
+ move x Dst
+
bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst=d =>
bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst |
i_bs_validate_unicode_retract Fail Dst Ms
diff --git a/erts/emulator/beam/packet_parser.c b/erts/emulator/beam/packet_parser.c
index 164994a98f..a349c3ff84 100644
--- a/erts/emulator/beam/packet_parser.c
+++ b/erts/emulator/beam/packet_parser.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -230,7 +230,7 @@ struct tpkt_head {
unsigned char packet_length[2]; /* size incl header, big-endian (?) */
};
-void packet_parser_init()
+void packet_parser_init(void)
{
static int done = 0;
if (!done) {
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 647f980e62..8e2b13136b 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -1441,8 +1441,8 @@ tailrecur_ne:
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
ASSERT(sz > 0 && sz < 17);
break;
- default:
- erts_exit(ERTS_ERROR_EXIT, "Unknown hashmap subsubtag\n");
+ default:
+ erts_exit(ERTS_ERROR_EXIT, "bad header");
}
goto term_array;
}
@@ -1983,6 +1983,11 @@ tailrecur_ne:
A minimal key can only be candidate as tie-breaker if we
have passed that hash value in the other tree (which means
the key did not exist in the other tree).
+
+ Collision node amendment:
+ The leafs in collision nodes are sorted in map-key order.
+ If keys are different but hashes are equal we advance the
+ one lagging behind key-wise.
*/
sp = PSTACK_PUSH(map_stack);
@@ -2395,12 +2400,19 @@ pop_next:
ASSERT(sp->is_hashmap);
if (j) {
/* Key diff found, enter phase 2 */
- if (hashmap_key_hash_cmp(sp->ap, sp->bp) < 0) {
+ int hash_cmp = hashmap_key_hash_cmp(sp->ap, sp->bp);
+ if (hash_cmp == 0) {
+ /* Hash collision. Collision nodes are sorted by map key
+ * order, so we advance the one with the lesser key */
+ hash_cmp = j;
+ }
+ if (hash_cmp < 0) {
sp->min_key = CAR(sp->ap);
sp->cmp_res = -1;
sp->ap = hashmap_iterator_next(&stack);
}
else {
+ ASSERT(hash_cmp > 0);
sp->min_key = CAR(sp->bp);
sp->cmp_res = 1;
sp->bp = hashmap_iterator_next(&b_stack);
@@ -2452,7 +2464,7 @@ pop_next:
sp->bp = hashmap_iterator_next(&b_stack);
if (!sp->ap) {
/* end of maps with identical keys */
- ASSERT(!sp->bp);
+ ASSERT(!sp->bp); /* as we assume indentical map sizes */
j = sp->cmp_res;
exact = sp->was_exact;
(void) PSTACK_POP(map_stack);
@@ -2488,14 +2500,21 @@ pop_next:
/* fall through */
case_HASHMAP_PHASE2_NEXT_STEP:
if (sp->ap || sp->bp) {
- if (hashmap_key_hash_cmp(sp->ap, sp->bp) < 0) {
+ int hash_cmp = hashmap_key_hash_cmp(sp->ap, sp->bp);
+ if (hash_cmp == 0) {
+ /* Hash collision. Collision nodes are sorted by map key
+ * order, so we advance the one with the lesser key */
+ hash_cmp = j;
+ }
+ if (hash_cmp < 0) {
ASSERT(sp->ap);
a = CAR(sp->ap);
b = sp->min_key;
ASSERT(exact);
WSTACK_PUSH(stack, OP_WORD(HASHMAP_PHASE2_IS_MIN_KEY_A));
}
- else { /* hash_cmp > 0 */
+ else {
+ ASSERT(hash_cmp > 0);
ASSERT(sp->bp);
a = CAR(sp->bp);
b = sp->min_key;
@@ -3749,7 +3768,7 @@ erts_ptr_id(void *ptr)
return ptr;
}
-const void *erts_get_stacklimit() {
+const void *erts_get_stacklimit(void) {
return ethr_get_stacklimit();
}
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index a902fd27ad..329c48172c 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -4421,7 +4421,7 @@ static void inet_init_sctp(void) {
}
#endif /* HAVE_SCTP */
-static int inet_init()
+static int inet_init(void)
{
if (!sock_init())
goto error;
@@ -13875,7 +13875,7 @@ static udp_descriptor* sctp_inet_copy(udp_descriptor* desc, SOCKET s,
#ifdef HAVE_UDP
-static int packet_inet_init()
+static int packet_inet_init(void)
{
sys_memzero((char *)&disassoc_sa, sizeof(disassoc_sa));
#ifdef AF_UNSPEC
@@ -15060,8 +15060,7 @@ static MultiTimerData *add_multi_timer(tcp_descriptor *desc, ErlDrvPort port,
-----------------------------------------------------------------------------*/
static int
-save_subscriber(subs, subs_pid)
-subs_list *subs; ErlDrvTermData subs_pid;
+save_subscriber(subs_list *subs, ErlDrvTermData subs_pid)
{
subs_list *tmp;
@@ -15083,8 +15082,7 @@ subs_list *subs; ErlDrvTermData subs_pid;
}
static void
-free_subscribers(subs)
-subs_list *subs;
+free_subscribers(subs_list *subs)
{
subs_list *this;
subs_list *next;
diff --git a/erts/emulator/internal_doc/BeamAsm.md b/erts/emulator/internal_doc/BeamAsm.md
index b9a739d897..4df4634d2d 100644
--- a/erts/emulator/internal_doc/BeamAsm.md
+++ b/erts/emulator/internal_doc/BeamAsm.md
@@ -385,8 +385,9 @@ not need the symbols in the executable.
Using the same data we can also produce a graph where the scheduler profile data
has been merged by using `sed`:
- ## Strip [0-9]+_ from all scheduler names
- sed -e 's/^[0-9]\+_//' out.folded > out.folded_sched
+ ## Strip [0-9]+_ and/or _[0-9]+ from all scheduler names
+ ## scheduler names changed in OTP26, hence two expressions
+ sed -e 's/^[0-9]\+_//' -e 's/^erts_\([^_]\+\)_[0-9]\+/erts_\1/' out.folded > out.folded_sched
## Create the svg
flamegraph.pl out.folded_sched > out_sched.svg
diff --git a/erts/emulator/nifs/common/prim_socket_int.h b/erts/emulator/nifs/common/prim_socket_int.h
index 90937d308e..9f753bf80b 100644
--- a/erts/emulator/nifs/common/prim_socket_int.h
+++ b/erts/emulator/nifs/common/prim_socket_int.h
@@ -352,6 +352,7 @@ typedef struct {
/* XXX Should be locked but too awkward and small gain */
BOOLEAN_T dbg;
BOOLEAN_T useReg;
+ BOOLEAN_T eei;
/* Registry stuff */
ErlNifPid regPid; /* Constant - not locked */
diff --git a/erts/emulator/nifs/common/prim_socket_nif.c b/erts/emulator/nifs/common/prim_socket_nif.c
index a46e44d53b..9d6755387d 100644
--- a/erts/emulator/nifs/common/prim_socket_nif.c
+++ b/erts/emulator/nifs/common/prim_socket_nif.c
@@ -1955,6 +1955,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(cmsg_cloexec); \
GLOBAL_ATOM_DECL(command); \
GLOBAL_ATOM_DECL(completion); \
+ GLOBAL_ATOM_DECL(completion_status); \
GLOBAL_ATOM_DECL(confirm); \
GLOBAL_ATOM_DECL(congestion); \
GLOBAL_ATOM_DECL(connect); \
@@ -2291,6 +2292,7 @@ ERL_NIF_TERM esock_atom_socket_tag; // This has a "special" name ('$socket')
LOCAL_ATOM_DECL(do); \
LOCAL_ATOM_DECL(dont); \
LOCAL_ATOM_DECL(dtor); \
+ LOCAL_ATOM_DECL(eei); \
LOCAL_ATOM_DECL(exclude); \
LOCAL_ATOM_DECL(false); \
LOCAL_ATOM_DECL(frag_needed); \
@@ -3844,7 +3846,7 @@ ERL_NIF_TERM esock_global_info(ErlNifEnv* env)
numBits, numSockets, numTypeDGrams, numTypeStreams,
numTypeSeqPkgs, numDomLocal, numDomInet, numDomInet6,
numProtoIP, numProtoTCP, numProtoUDP, numProtoSCTP,
- sockDbg, iovMax, dbg, useReg, iow;
+ sockDbg, iovMax, dbg, useReg, iow, eei;
MLOCK(data.cntMtx);
numBits = MKUI(env, ESOCK_COUNTER_SIZE);
@@ -3860,6 +3862,7 @@ ERL_NIF_TERM esock_global_info(ErlNifEnv* env)
numProtoUDP = MKUI(env, data.numProtoUDP);
numProtoSCTP = MKUI(env, data.numProtoSCTP);
sockDbg = BOOL2ATOM(data.sockDbg);
+ eei = BOOL2ATOM(data.eei);
MUNLOCK(data.cntMtx);
iovMax = MKI(env, data.iov_max);
@@ -3891,6 +3894,7 @@ ERL_NIF_TERM esock_global_info(ErlNifEnv* env)
ERL_NIF_TERM
keys[] = {esock_atom_debug,
atom_socket_debug,
+ atom_eei,
esock_atom_use_registry,
atom_iow,
esock_atom_counters,
@@ -3898,6 +3902,7 @@ ERL_NIF_TERM esock_global_info(ErlNifEnv* env)
atom_io_backend},
vals[] = {dbg,
sockDbg,
+ eei,
useReg,
iow,
gcnt,
@@ -13141,6 +13146,13 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_iow,
ESOCK_NIF_IOW_DEFAULT);
+ /* --enable-extended-error-info */
+#if defined(ESOCK_USE_EXTENDED_ERROR_INFO)
+ data.eei = TRUE;
+#else
+ data.eei = FALSE;
+#endif
+
/* --esock-debug-file=<filename> */
{
char *debug_filename;
diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h
index 2613fe5a1e..9c3381f975 100644
--- a/erts/emulator/nifs/common/socket_int.h
+++ b/erts/emulator/nifs/common/socket_int.h
@@ -242,6 +242,7 @@ typedef long ssize_t;
GLOBAL_ATOM_DEF(cmsg_cloexec); \
GLOBAL_ATOM_DEF(command); \
GLOBAL_ATOM_DEF(completion); \
+ GLOBAL_ATOM_DEF(completion_status); \
GLOBAL_ATOM_DEF(confirm); \
GLOBAL_ATOM_DEF(congestion); \
GLOBAL_ATOM_DEF(connect); \
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 8eeb98dba7..a1c3e7eddc 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -2371,6 +2371,18 @@ ERL_NIF_TERM esock_errno_to_term(ErlNifEnv* env, int err)
break;
#endif
+#if defined(ERROR_INVALID_NETNAME)
+ case ERROR_INVALID_NETNAME:
+ return MKA(env, "invalid_netname");
+ break;
+#endif
+
+#if defined(ERROR_MORE_DATA)
+ case ERROR_MORE_DATA:
+ return MKA(env, "more_data");
+ break;
+#endif
+
default:
{
char* str = erl_errno_id(err);
@@ -2666,7 +2678,7 @@ MSG_FUNCS
*/
extern
-ErlNifTime esock_timestamp()
+ErlNifTime esock_timestamp(void)
{
ErlNifTime monTime = enif_monotonic_time(ERL_NIF_USEC);
ErlNifTime offTime = enif_time_offset(ERL_NIF_USEC);
diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h
index 04f0cc3d94..c16803bbdc 100644
--- a/erts/emulator/nifs/common/socket_util.h
+++ b/erts/emulator/nifs/common/socket_util.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,8 +53,7 @@
__LINE__, \
(RI), (I))
-#define ESOCK_VERBOSE_ERRNO 1
-#if defined(ESOCK_VERBOSE_ERRNO)
+#if defined(ESOCK_USE_EXTENDED_ERROR_INFO)
#define ENO2T(E, ENO) MKEEI((E), \
MKI((E), (ENO)), \
esock_errno_to_term((E), (ENO)))
diff --git a/erts/emulator/nifs/unix/unix_socket_syncio.c b/erts/emulator/nifs/unix/unix_socket_syncio.c
index 3e3cfcaeef..644400aeb5 100644
--- a/erts/emulator/nifs/unix/unix_socket_syncio.c
+++ b/erts/emulator/nifs/unix/unix_socket_syncio.c
@@ -29,6 +29,8 @@
# include "config.h"
#endif
+#ifdef ESOCK_ENABLE
+
#ifdef HAVE_SENDFILE
#if defined(__linux__) || (defined(__sun) && defined(__SVR4))
#include <sys/sendfile.h>
@@ -7385,3 +7387,4 @@ void essio_down_reader(ErlNifEnv* env,
}
+#endif
diff --git a/erts/emulator/nifs/win32/win_socket_asyncio.c b/erts/emulator/nifs/win32/win_socket_asyncio.c
index f91e7edc48..b7d1f424fd 100644
--- a/erts/emulator/nifs/win32/win_socket_asyncio.c
+++ b/erts/emulator/nifs/win32/win_socket_asyncio.c
@@ -83,6 +83,8 @@
# include "config.h"
#endif
+#ifdef ESOCK_ENABLE
+
// #include <Ws2def.h>
// #include <winsock2.h>
// #include <windows.h>
@@ -719,6 +721,21 @@ static BOOLEAN_T esaio_completion_send(ESAIOThreadData* dataP,
ErlNifPid* opCaller,
ESAIOOpDataSend* opDataP,
int error);
+static void esaio_completion_send_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSend* opDataP);
+static void esaio_completion_send_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSend* opDataP);
+static void esaio_completion_send_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSend* opDataP,
+ int error);
static void esaio_completion_send_completed(ErlNifEnv* env,
ESockDescriptor* descP,
OVERLAPPED* ovl,
@@ -748,6 +765,21 @@ static BOOLEAN_T esaio_completion_sendto(ESAIOThreadData* dataP,
ErlNifPid* opCaller,
ESAIOOpDataSendTo* opDataP,
int error);
+static void esaio_completion_sendto_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendTo* opDataP);
+static void esaio_completion_sendto_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendTo* opDataP);
+static void esaio_completion_sendto_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendTo* opDataP,
+ int error);
static void esaio_completion_sendto_fail(ErlNifEnv* env,
ESockDescriptor* descP,
int error,
@@ -759,6 +791,21 @@ static BOOLEAN_T esaio_completion_sendmsg(ESAIOThreadData* dataP,
ErlNifPid* opCaller,
ESAIOOpDataSendMsg* opDataP,
int error);
+static void esaio_completion_sendmsg_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendMsg* opDataP);
+static void esaio_completion_sendmsg_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendMsg* opDataP);
+static void esaio_completion_sendmsg_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendMsg* opDataP,
+ int error);
static void esaio_completion_sendmsg_fail(ErlNifEnv* env,
ESockDescriptor* descP,
int error,
@@ -770,6 +817,21 @@ static BOOLEAN_T esaio_completion_recv(ESAIOThreadData* dataP,
ErlNifPid* opCaller,
ESAIOOpDataRecv* opDataP,
int error);
+static void esaio_completion_recv_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecv* opDataP);
+static void esaio_completion_recv_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecv* opDataP);
+static void esaio_completion_recv_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecv* opDataP,
+ int error);
static void esaio_completion_recv_completed(ErlNifEnv* env,
ESockDescriptor* descP,
OVERLAPPED* ovl,
@@ -815,6 +877,27 @@ static BOOLEAN_T esaio_completion_recvfrom(ESAIOThreadData* dataP,
ErlNifPid* opCaller,
ESAIOOpDataRecvFrom* opDataP,
int error);
+static void esaio_completion_recvfrom_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvFrom* opDataP);
+static void esaio_completion_recvfrom_more_data(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvFrom* opDataP,
+ int error);
+static void esaio_completion_recvfrom_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvFrom* opDataP);
+static void esaio_completion_recvfrom_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvFrom* opDataP,
+ int error);
static void esaio_completion_recvfrom_completed(ErlNifEnv* env,
ESockDescriptor* descP,
OVERLAPPED* ovl,
@@ -845,6 +928,21 @@ static BOOLEAN_T esaio_completion_recvmsg(ESAIOThreadData* dataP,
ErlNifPid* opCaller,
ESAIOOpDataRecvMsg* opDataP,
int error);
+static void esaio_completion_recvmsg_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvMsg* opDataP);
+static void esaio_completion_recvmsg_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvMsg* opDataP);
+static void esaio_completion_recvmsg_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvMsg* opDataP,
+ int error);
static void esaio_completion_recvmsg_completed(ErlNifEnv* env,
ESockDescriptor* descP,
OVERLAPPED* ovl,
@@ -5719,7 +5817,7 @@ void esaio_completion_connect_failure(ErlNifEnv* env,
if (descP->connectorP != NULL) {
/* Figure out the reason */
ERL_NIF_TERM reason = MKT2(env,
- esock_atom_get_overlapped_result,
+ esock_atom_completion_status,
ENO2T(env, error));
/* Inform the user waiting for a reply */
@@ -6007,6 +6105,12 @@ void esaio_completion_accept_success(ErlNifEnv* env,
/* *Maybe* update socket (read) state
* (depends on if the queue is now empty)
*/
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_accept_success(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->acceptorsQ.first == NULL)), descP->readState) );
if (descP->acceptorsQ.first == NULL)
descP->readState &= ~ESOCK_STATE_SELECTED;
}
@@ -6029,7 +6133,6 @@ void esaio_completion_accept_aborted(ErlNifEnv* env,
ESAIOOpDataAccept* opDataP)
{
ESockRequestor req;
- ERL_NIF_TERM reason;
if (esock_acceptor_get(env, descP,
&opDataP->accRef,
@@ -6069,6 +6172,12 @@ void esaio_completion_accept_aborted(ErlNifEnv* env,
/* *Maybe* update socket (read) state
* (depends on if the queue is now empty)
*/
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_accept_aborted(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->acceptorsQ.first == NULL)), descP->readState) );
if (descP->acceptorsQ.first == NULL) {
descP->readState &= ~ESOCK_STATE_SELECTED;
}
@@ -6095,7 +6204,7 @@ void esaio_completion_accept_failure(ErlNifEnv* env,
&req)) {
reason = MKT2(env,
- esock_atom_get_overlapped_result,
+ esock_atom_completion_status,
ENO2T(env, error));
/* Inform the user waiting for a reply */
@@ -6109,6 +6218,12 @@ void esaio_completion_accept_failure(ErlNifEnv* env,
/* *Maybe* update socket (read) state
* (depends on if the queue is now empty)
*/
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_accept_failure(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->acceptorsQ.first == NULL)), descP->readState) );
if (descP->acceptorsQ.first == NULL) {
descP->readState &= ~ESOCK_STATE_SELECTED;
}
@@ -6370,40 +6485,9 @@ BOOLEAN_T esaio_completion_send(ESAIOThreadData* dataP,
("WIN-ESAIO", "esaio_completion_send(%d) -> no error"
"\r\n", descP->sock) );
MLOCK(descP->writeMtx);
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
- if (IS_OPEN(descP->writeState)) {
- esaio_completion_send_completed(env, descP,
- ovl,
- opEnv,
- opCaller,
- opDataP->sockRef,
- opDataP->sendRef,
- opDataP->wbuf.len,
- &req);
- } else {
- /* A completed (active) request for a socket that is not open.
- * Is this even possible?
- * A race (completed just as the socket was closed).
- */
- esaio_completion_send_not_active(descP);
- }
- } else {
- /* Request was actually completed directly
- * (and was therefor not put into the "queue")
- * => Nothing to do here, other than cleanup (see below).
- */
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_send_success(env, descP, ovl, opEnv,
+ opCaller, opDataP);
MUNLOCK(descP->writeMtx);
break;
@@ -6416,55 +6500,9 @@ BOOLEAN_T esaio_completion_send(ESAIOThreadData* dataP,
/* *** SAME MTX LOCK ORDER FOR ALL OPs *** */
MLOCK(descP->readMtx);
MLOCK(descP->writeMtx);
- /* The only thing *we* do that could cause an abort is the
- * 'CancelIoEx' call, which we do when closing the socket
- * (or cancel a request).
- * But if we have done that;
- * - Socket state will not be 'open' and
- * - we have also set closer (pid and ref).
- */
-
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
-
- reason = esock_atom_closed,
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
-
- /* The socket not being open (assumed closing),
- * means we are in the closing phase...
- */
- if (! IS_OPEN(descP->writeState)) {
-
- /* We can only send the 'close' message to the closer
- * when all requests has been processed!
- */
-
- /* Check "our" queue */
- if (descP->writersQ.first == NULL) {
-
- /* Check "other" queue(s) and if there is a closer pid */
- if ((descP->readersQ.first == NULL) &&
- (descP->acceptorsQ.first == NULL)) {
-
- esaio_stop(env, descP);
- }
- }
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_send_aborted(env, descP, opCaller, opDataP);
- }
MUNLOCK(descP->writeMtx);
MUNLOCK(descP->readMtx);
break;
@@ -6475,36 +6513,9 @@ BOOLEAN_T esaio_completion_send(ESAIOThreadData* dataP,
"esaio_completion_send(%d) -> operation unknown failure"
"\r\n", descP->sock) );
MLOCK(descP->writeMtx);
- /* We do not know what this is
- * but we can "assume" that the request failed so we need to
- * remove it from the "queue" if its still there...
- * And cleanup...
- */
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
-
- reason = MKT2(env,
- esock_atom_get_overlapped_result,
- ENO2T(env, error));
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
- esaio_completion_send_fail(env, descP, error, FALSE);
-
- } else {
- esaio_completion_send_fail(env, descP, error, TRUE);
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_send_failure(env, descP, opCaller, opDataP, error);
+
MUNLOCK(descP->writeMtx);
break;
}
@@ -6528,6 +6539,184 @@ BOOLEAN_T esaio_completion_send(ESAIOThreadData* dataP,
}
+
+/* *** esaio_completion_send_success ***
+ * The 'send' operation was successful.
+ */
+static
+void esaio_completion_send_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSend* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+ if (IS_OPEN(descP->writeState)) {
+ esaio_completion_send_completed(env, descP, ovl, opEnv,
+ opCaller,
+ opDataP->sockRef,
+ opDataP->sendRef,
+ opDataP->wbuf.len,
+ &req);
+ } else {
+ /* A completed (active) request for a socket that is not open.
+ * Is this even possible?
+ * A race (completed just as the socket was closed).
+ */
+ esaio_completion_send_not_active(descP);
+ }
+
+ } else {
+ /* Request was actually completed directly
+ * (and was therefor not put into the "queue")
+ * => Nothing to do here, other than cleanup (see below).
+ */
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_send_success(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+
+/* *** esaio_completion_send_aborted ***
+ * The only thing *we* do that could cause an abort is the
+ * 'CancelIoEx' call, which we do when closing the socket
+ * (or cancel a request).
+ * But if we have done that;
+ * - Socket state will not be 'open' and
+ * - we have also set closer (pid and ref).
+ */
+
+static
+void esaio_completion_send_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSend* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+
+ ERL_NIF_TERM reason = esock_atom_closed;
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+
+ /* The socket not being open (assumed closing),
+ * means we are in the closing phase...
+ */
+ if (! IS_OPEN(descP->writeState)) {
+
+ /* We can only send the 'close' message to the closer
+ * when all requests has been processed!
+ */
+
+ /* Check "our" queue */
+ if (descP->writersQ.first == NULL) {
+
+ /* Check "other" queue(s) and if there is a closer pid */
+ if ((descP->readersQ.first == NULL) &&
+ (descP->acceptorsQ.first == NULL)) {
+
+ esaio_stop(env, descP);
+
+ }
+ }
+ }
+
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_send_aborted(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+
+/* *** esaio_completion_send_failure *
+ * A "general" failure happened while performing the 'send' operation.
+ */
+static
+void esaio_completion_send_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSend* opDataP,
+ int error)
+{
+ ESockRequestor req;
+ ERL_NIF_TERM reason;
+
+ /* We do not know what this is
+ * but we can "assume" that the request failed so we need to
+ * remove it from the "queue" if its still there...
+ * And cleanup...
+ */
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+
+ reason = MKT2(env,
+ esock_atom_completion_status,
+ ENO2T(env, error));
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+ esaio_completion_send_fail(env, descP, error, FALSE);
+
+ } else {
+ esaio_completion_send_fail(env, descP, error, TRUE);
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_send_failure(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
/* *** esaio_completion_send_completed ***
* The send request has completed.
*/
@@ -6785,40 +6974,9 @@ BOOLEAN_T esaio_completion_sendto(ESAIOThreadData* dataP,
("WIN-ESAIO", "esaio_completion_sendto(%d) -> no error"
"\r\n", descP->sock) );
MLOCK(descP->writeMtx);
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
- if (IS_OPEN(descP->writeState)) {
- esaio_completion_send_completed(env, descP,
- ovl,
- opEnv,
- opCaller,
- opDataP->sockRef,
- opDataP->sendRef,
- opDataP->wbuf.len,
- &req);
- } else {
- /* A completed (active) request for a socket that is not open.
- * Is this even possible?
- * A race (completed just as the socket was closed).
- */
- esaio_completion_send_not_active(descP);
- }
- } else {
- /* Request was actually completed directly
- * (and was therefor not put into the "queue")
- * => Nothing to do here, other than cleanup (see below).
- */
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_sendto_success(env, descP, ovl, opEnv,
+ opCaller, opDataP);
MUNLOCK(descP->writeMtx);
break;
@@ -6831,55 +6989,8 @@ BOOLEAN_T esaio_completion_sendto(ESAIOThreadData* dataP,
/* *** SAME MTX LOCK ORDER FOR ALL OPs *** */
MLOCK(descP->readMtx);
MLOCK(descP->writeMtx);
- /* The only thing *we* do that could cause an abort is the
- * 'CancelIoEx' call, which we do when closing the socket
- * (or cancel a request).
- * But if we have done that;
- * - Socket state will not be 'open' and
- * - we have also set closer (pid and ref).
- */
-
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
-
- reason = esock_atom_closed,
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
-
- /* The socket not being open (assumed closing),
- * means we are in the closing phase...
- */
- if (! IS_OPEN(descP->writeState)) {
-
- /* We can only send the 'close' message to the closer
- * when all requests has been processed!
- */
-
- /* Check "our" queue */
- if (descP->writersQ.first == NULL) {
-
- /* Check "other" queue(s) and if there is a closer pid */
- if ((descP->readersQ.first == NULL) &&
- (descP->acceptorsQ.first == NULL)) {
-
- esaio_stop(env, descP);
-
- }
- }
- }
-
- }
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_sendto_aborted(env, descP, opCaller, opDataP);
MUNLOCK(descP->writeMtx);
MUNLOCK(descP->readMtx);
@@ -6891,35 +7002,8 @@ BOOLEAN_T esaio_completion_sendto(ESAIOThreadData* dataP,
"esaio_completion_sendto(%d) -> operation unknown failure"
"\r\n", descP->sock) );
MLOCK(descP->writeMtx);
- /* We do not know what this is
- * but we can "assume" that the request failed so we need to
- * remove it from the "queue" if its still there...
- * And cleanup...
- */
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
- reason = MKT2(env,
- esock_atom_get_overlapped_result,
- ENO2T(env, error));
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
- esaio_completion_sendto_fail(env, descP, error, FALSE);
-
- } else {
- esaio_completion_sendto_fail(env, descP, error, TRUE);
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_sendto_failure(env, descP, opCaller, opDataP, error);
MUNLOCK(descP->writeMtx);
break;
@@ -6945,6 +7029,180 @@ BOOLEAN_T esaio_completion_sendto(ESAIOThreadData* dataP,
+/* *** esaio_completion_sendto_suuccess *** */
+static
+void esaio_completion_sendto_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendTo* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+ if (IS_OPEN(descP->writeState)) {
+ esaio_completion_send_completed(env, descP, ovl, opEnv,
+ opCaller,
+ opDataP->sockRef,
+ opDataP->sendRef,
+ opDataP->wbuf.len,
+ &req);
+ } else {
+ /* A completed (active) request for a socket that is not open.
+ * Is this even possible?
+ * A race (completed just as the socket was closed).
+ */
+ esaio_completion_send_not_active(descP);
+ }
+
+ } else {
+ /* Request was actually completed directly
+ * (and was therefor not put into the "queue")
+ * => Nothing to do here, other than cleanup (see below).
+ */
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_sendto_success(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+
+/* *** esaio_completion_sendto_aborted ***
+ * The only thing *we* do that could cause an abort is the
+ * 'CancelIoEx' call, which we do when closing the socket
+ * (or cancel a request).
+ * But if we have done that;
+ * - Socket state will not be 'open' and
+ * - we have also set closer (pid and ref).
+ */
+
+static
+void esaio_completion_sendto_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendTo* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+
+ ERL_NIF_TERM reason = esock_atom_closed;
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+
+ /* The socket not being open (assumed closing),
+ * means we are in the closing phase...
+ */
+ if (! IS_OPEN(descP->writeState)) {
+
+ /* We can only send the 'close' message to the closer
+ * when all requests has been processed!
+ */
+
+ /* Check "our" queue */
+ if (descP->writersQ.first == NULL) {
+
+ /* Check "other" queue(s) and if there is a closer pid */
+ if ((descP->readersQ.first == NULL) &&
+ (descP->acceptorsQ.first == NULL)) {
+
+ esaio_stop(env, descP);
+
+ }
+ }
+ }
+
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_sendto_aborted(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+}
+
+
+/* *** esaio_completion_sendto_failure *
+ * A "general" failure happened while performing the 'sendto' operation.
+ */
+static
+void esaio_completion_sendto_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendTo* opDataP,
+ int error)
+{
+ ESockRequestor req;
+ ERL_NIF_TERM reason;
+
+ /* We do not know what this is
+ * but we can "assume" that the request failed so we need to
+ * remove it from the "queue" if its still there...
+ * And cleanup...
+ */
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+
+ reason = MKT2(env,
+ esock_atom_completion_status,
+ ENO2T(env, error));
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+ esaio_completion_sendto_fail(env, descP, error, FALSE);
+
+ } else {
+ esaio_completion_sendto_fail(env, descP, error, TRUE);
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_sendto_failure(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+
/* *** esaio_completion_sendto_fail ***
* Unknown operation failure.
*/
@@ -7007,50 +7265,10 @@ BOOLEAN_T esaio_completion_sendmsg(ESAIOThreadData* dataP,
("WIN-ESAIO", "esaio_completion_sendmsg(%d) -> no error"
"\r\n", descP->sock) );
MLOCK(descP->writeMtx);
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
- if (IS_OPEN(descP->writeState)) {
-
- DWORD toWrite = 0;
-
- /* Calculate how much data *in total*
- * we was supposed to write */
- for (int i = 0; i < opDataP->iovec->iovcnt; i++) {
- toWrite += opDataP->iovec->iov[i].iov_len;
- }
- esaio_completion_send_completed(env, descP,
- ovl,
- opEnv,
- opCaller,
- opDataP->sockRef,
- opDataP->sendRef,
- toWrite,
- &req);
+ esaio_completion_sendmsg_success(env, descP, ovl, opEnv,
+ opCaller, opDataP);
- } else {
- /* A completed (active) request for a socket that is not open.
- * Is this even possible?
- * A race (completed just as the socket was closed).
- */
- esaio_completion_send_not_active(descP);
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
-
- } else {
- /* Request was actually completed directly
- * (and was therefor not put into the "queue")
- * => Nothing to do here, other than cleanup (see below).
- */
- }
MUNLOCK(descP->writeMtx);
break;
@@ -7062,55 +7280,9 @@ BOOLEAN_T esaio_completion_sendmsg(ESAIOThreadData* dataP,
/* *** SAME MTX LOCK ORDER FOR ALL OPs *** */
MLOCK(descP->readMtx);
MLOCK(descP->writeMtx);
- /* The only thing *we* do that could cause an abort is the
- * 'CancelIoEx' call, which we do when closing the socket
- * (or cancel a request).
- * But if we have done that;
- * - Socket state will not be 'open' and
- * - we have also set closer (pid and ref).
- */
-
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
-
- reason = esock_atom_closed,
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
-
- /* The socket not being open (assumed closing),
- * means we are in the closing phase...
- */
- if (! IS_OPEN(descP->writeState)) {
-
- /* We can only send the 'close' message to the closer
- * when all requests has been processed!
- */
-
- /* Check "our" queue */
- if (descP->writersQ.first == NULL) {
-
- /* Check "other" queue(s) and if there is a closer pid */
- if ((descP->readersQ.first == NULL) &&
- (descP->acceptorsQ.first == NULL)) {
-
- esaio_stop(env, descP);
- }
- }
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_sendmsg_aborted(env, descP, opCaller, opDataP);
- }
MUNLOCK(descP->writeMtx);
MUNLOCK(descP->readMtx);
break;
@@ -7121,35 +7293,9 @@ BOOLEAN_T esaio_completion_sendmsg(ESAIOThreadData* dataP,
"esaio_completion_sendmsg(%d) -> operation unknown failure"
"\r\n", descP->sock) );
MLOCK(descP->writeMtx);
- /* We do not know what this is
- * but we can "assume" that the request failed so we need to
- * remove it from the "queue" if its still there...
- * And cleanup...
- */
- if (esock_writer_get(env, descP,
- &opDataP->sendRef,
- opCaller,
- &req)) {
-
- reason = MKT2(env,
- esock_atom_get_overlapped_result,
- ENO2T(env, error));
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
- esaio_completion_sendmsg_fail(env, descP, error, FALSE);
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->writersQ.first == NULL) {
- descP->writeState &= ~ESOCK_STATE_SELECTED;
- }
- } else {
- esaio_completion_sendmsg_fail(env, descP, error, TRUE);
- }
+ esaio_completion_sendmsg_failure(env, descP, opCaller, opDataP, error);
+
MUNLOCK(descP->writeMtx);
break;
}
@@ -7176,6 +7322,188 @@ BOOLEAN_T esaio_completion_sendmsg(ESAIOThreadData* dataP,
}
+/* *** esaio_completion_sendmsg_suuccess *** */
+static
+void esaio_completion_sendmsg_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendMsg* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+ if (IS_OPEN(descP->writeState)) {
+
+ DWORD toWrite = 0;
+
+ /* Calculate how much data *in total*
+ * we was supposed to write */
+ for (int i = 0; i < opDataP->iovec->iovcnt; i++) {
+ toWrite += opDataP->iovec->iov[i].iov_len;
+ }
+
+ esaio_completion_send_completed(env, descP, ovl, opEnv,
+ opCaller,
+ opDataP->sockRef,
+ opDataP->sendRef,
+ toWrite,
+ &req);
+
+ } else {
+ /* A completed (active) request for a socket that is not open.
+ * Is this even possible?
+ * A race (completed just as the socket was closed).
+ */
+ esaio_completion_send_not_active(descP);
+ }
+
+ } else {
+ /* Request was actually completed directly
+ * (and was therefor not put into the "queue")
+ * => Nothing to do here, other than cleanup (see below).
+ */
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_sendmsg_success(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+/* *** esaio_completion_sendmsg_aborted ***
+ * The only thing *we* do that could cause an abort is the
+ * 'CancelIoEx' call, which we do when closing the socket
+ * (or cancel a request).
+ * But if we have done that;
+ * - Socket state will not be 'open' and
+ * - we have also set closer (pid and ref).
+ */
+
+static
+void esaio_completion_sendmsg_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendMsg* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+
+ ERL_NIF_TERM reason = esock_atom_closed;
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+
+ /* The socket not being open (assumed closing),
+ * means we are in the closing phase...
+ */
+ if (! IS_OPEN(descP->writeState)) {
+
+ /* We can only send the 'close' message to the closer
+ * when all requests has been processed!
+ */
+
+ /* Check "our" queue */
+ if (descP->writersQ.first == NULL) {
+
+ /* Check "other" queue(s) and if there is a closer pid */
+ if ((descP->readersQ.first == NULL) &&
+ (descP->acceptorsQ.first == NULL)) {
+
+ esaio_stop(env, descP);
+
+ }
+ }
+ }
+
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_sendmsg_aborted(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+/* *** esaio_completion_sendmsg_failure *
+ * A "general" failure happened while performing the 'sendmsg' operation.
+ */
+static
+void esaio_completion_sendmsg_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataSendMsg* opDataP,
+ int error)
+{
+ ESockRequestor req;
+ ERL_NIF_TERM reason;
+
+ /* We do not know what this is
+ * but we can "assume" that the request failed so we need to
+ * remove it from the "queue" if its still there...
+ * And cleanup...
+ */
+ if (esock_writer_get(env, descP,
+ &opDataP->sendRef,
+ opCaller,
+ &req)) {
+
+ reason = MKT2(env,
+ esock_atom_completion_status,
+ ENO2T(env, error));
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+ esaio_completion_sendmsg_fail(env, descP, error, FALSE);
+
+ } else {
+ esaio_completion_sendmsg_fail(env, descP, error, TRUE);
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_sendmsg_success(%d) -> "
+ "maybe (%s) update (write) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->writersQ.first == NULL)), descP->writeState) );
+ if (descP->writersQ.first == NULL) {
+ descP->writeState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
/* *** esaio_completion_sendmsg_fail ***
* Unknown operation failure.
@@ -7238,39 +7566,10 @@ BOOLEAN_T esaio_completion_recv(ESAIOThreadData* dataP,
("WIN-ESAIO", "esaio_completion_recv(%d) -> no error"
"\r\n", descP->sock) );
MLOCK(descP->readMtx);
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
- if (IS_OPEN(descP->readState)) {
- esaio_completion_recv_completed(env, descP,
- ovl,
- opEnv, opCaller, opDataP,
- &req);
- } else {
- /* A completed (active) request for a socket that is not open.
- * Is this even possible?
- * A race (completed just as the socket was closed).
- */
- esaio_completion_recv_not_active(descP);
- FREE_BIN( &opDataP->buf );
- }
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_recv_success(env, descP, ovl, opEnv,
+ opCaller, opDataP);
- } else {
- /* Request was actually completed directly
- * (and was therefor not put into the "queue")
- * => Nothing to do here, other than cleanup (see below).
- * => But we do not free the "buffer" since it was "used up"
- * when we (as assumed) got the result (directly)...
- */
- }
MUNLOCK(descP->readMtx);
break;
@@ -7282,55 +7581,9 @@ BOOLEAN_T esaio_completion_recv(ESAIOThreadData* dataP,
/* *** SAME MTX LOCK ORDER FOR ALL OPs *** */
MLOCK(descP->readMtx);
MLOCK(descP->writeMtx);
- /* The only thing *we* do that could cause an abort is the
- * 'CancelIoEx' call, which we do when closing the socket
- * (or cancel a request).
- * But if we have done that;
- * - Socket state will not be 'open' and
- * - we have also set closer (pid and ref).
- */
-
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
- reason = esock_atom_closed,
+ esaio_completion_recv_aborted(env, descP, opCaller, opDataP);
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
-
- /* The socket not being open (assumed closing),
- * means we are in the closing phase...
- */
- if (! IS_OPEN(descP->readState)) {
-
- /* We can only send the 'close' message to the closer
- * when all requests has been processed!
- */
-
- /* Check "our" queue */
- if (descP->readersQ.first == NULL) {
-
- /* Check "other" queue(s) and if there is a closer pid */
- if ((descP->writersQ.first == NULL) &&
- (descP->acceptorsQ.first == NULL)) {
-
- esaio_stop(env, descP);
-
- }
- }
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
- }
- FREE_BIN( &opDataP->buf );
MUNLOCK(descP->writeMtx);
MUNLOCK(descP->readMtx);
break;
@@ -7341,36 +7594,9 @@ BOOLEAN_T esaio_completion_recv(ESAIOThreadData* dataP,
"esaio_completion_recv(%d) -> operation unknown failure"
"\r\n", descP->sock) );
MLOCK(descP->readMtx);
- /* We do not know what this is
- * but we can "assume" that the request failed so we need to
- * remove it from the "queue" if its still there...
- * And cleanup...
- */
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
- /* Figure out the reason */
- reason = MKT2(env,
- esock_atom_get_overlapped_result,
- ENO2T(env, error));
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
- esaio_completion_recv_fail(env, descP, error, FALSE);
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
-
- } else {
- esaio_completion_recv_fail(env, descP, error, TRUE);
- }
- FREE_BIN( &opDataP->buf );
+
+ esaio_completion_recv_failure(env, descP, opCaller, opDataP, error);
+
MUNLOCK(descP->readMtx);
break;
}
@@ -7385,13 +7611,187 @@ BOOLEAN_T esaio_completion_recv(ESAIOThreadData* dataP,
esock_free_env("esaio_completion_recv - op cleanup", opEnv);
SSDBG( descP,
- ("WIN-ESAIO", "esaio_completion_recv {%d} -> done\r\n",
+ ("WIN-ESAIO", "esaio_completion_recv(%d) -> done\r\n",
descP->sock) );
return FALSE;
}
+static
+void esaio_completion_recv_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecv* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+ if (IS_OPEN(descP->readState)) {
+ esaio_completion_recv_completed(env, descP, ovl, opEnv,
+ opCaller, opDataP,
+ &req);
+ } else {
+ /* A completed (active) request for a socket that is not open.
+ * Is this even possible?
+ * A race (completed just as the socket was closed).
+ */
+ esaio_completion_recv_not_active(descP);
+ FREE_BIN( &opDataP->buf );
+ }
+
+ } else {
+ /* Request was actually completed directly
+ * (and was therefor not put into the "queue")
+ * => Nothing to do here, other than cleanup (see below).
+ * => But we do not free the "buffer" since it was "used up"
+ * when we (as assumed) got the result (directly)...
+ */
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recv_success(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+/* *** esaio_completion_recv_aborted ***
+ * The only thing *we* do that could cause an abort is the
+ * 'CancelIoEx' call, which we do when closing the socket
+ * (or cancel a request).
+ * But if we have done that;
+ * - Socket state will not be 'open' and
+ * - we have also set closer (pid and ref).
+ */
+
+static
+void esaio_completion_recv_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecv* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+
+ ERL_NIF_TERM reason = esock_atom_closed;
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+
+ /* The socket not being open (assumed closing),
+ * means we are in the closing phase...
+ */
+ if (! IS_OPEN(descP->readState)) {
+
+ /* We can only send the 'close' message to the closer
+ * when all requests has been processed!
+ */
+
+ /* Check "our" queue */
+ if (descP->readersQ.first == NULL) {
+
+ /* Check "other" queue(s) and if there is a closer pid */
+ if ((descP->writersQ.first == NULL) &&
+ (descP->acceptorsQ.first == NULL)) {
+
+ esaio_stop(env, descP);
+
+ }
+ }
+ }
+ }
+
+ FREE_BIN( &opDataP->buf );
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recv_aborted(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+/* *** esaio_completion_recv_failure *
+ * A "general" failure happened while performing the 'recv' operation.
+ */
+static
+void esaio_completion_recv_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecv* opDataP,
+ int error)
+{
+ ESockRequestor req;
+ ERL_NIF_TERM reason;
+
+ /* We do not know what this is
+ * but we can "assume" that the request failed so we need to
+ * remove it from the "queue" if its still there...
+ * And cleanup...
+ */
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+ /* Figure out the reason */
+ reason = MKT2(env,
+ esock_atom_completion_status,
+ ENO2T(env, error));
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+ esaio_completion_recv_fail(env, descP, error, FALSE);
+
+ } else {
+ esaio_completion_recv_fail(env, descP, error, TRUE);
+ }
+
+ FREE_BIN( &opDataP->buf );
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recv_failure(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
/* *** esaio_completion_recv_completed ***
* The recv request has completed.
@@ -7863,38 +8263,24 @@ BOOLEAN_T esaio_completion_recvfrom(ESAIOThreadData* dataP,
("WIN-ESAIO", "esaio_completion_recvfrom(%d) -> no error"
"\r\n", descP->sock) );
MLOCK(descP->readMtx);
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
- if (IS_OPEN(descP->readState)) {
- esaio_completion_recvfrom_completed(env, descP,
- ovl, opEnv, opCaller,
- opDataP, &req);
- } else {
- /* A completed (active) request for a socket that is not open.
- * Is this even possible?
- * A race (completed just as the socket was closed).
- */
- esaio_completion_recv_not_active(descP);
- FREE_BIN( &opDataP->buf );
- }
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_recvfrom_success(env, descP, ovl, opEnv,
+ opCaller, opDataP);
+
+ MUNLOCK(descP->readMtx);
+ break;
+
+ case ERROR_MORE_DATA:
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvfrom(%d) -> more data"
+ "\r\n", descP->sock) );
+ MLOCK(descP->readMtx);
+
+ esaio_completion_recvfrom_more_data(env, descP,
+ opEnv, opCaller, opDataP,
+ error);
- } else {
- /* Request was actually completed directly
- * (and was therefor not put into the "queue")
- * => Nothing to do here, other than cleanup (see below).
- * => But we do not free the "buffer" since it was "used up"
- * when we (as assumed) got the result (directly)...
- */
- }
MUNLOCK(descP->readMtx);
break;
@@ -7906,56 +8292,9 @@ BOOLEAN_T esaio_completion_recvfrom(ESAIOThreadData* dataP,
/* *** SAME MTX LOCK ORDER FOR ALL OPs *** */
MLOCK(descP->readMtx);
MLOCK(descP->writeMtx);
- /* The only thing *we* do that could cause an abort is the
- * 'CancelIoEx' call, which we do when closing the socket
- * (or cancel a request).
- * But if we have done that;
- * - Socket state will not be 'open' and
- * - we have also set closer (pid and ref).
- */
-
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
-
- reason = esock_atom_closed,
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
+ esaio_completion_recvfrom_aborted(env, descP, opCaller, opDataP);
- /* The socket not being open (assumed closing),
- * means we are in the closing phase...
- */
- if (! IS_OPEN(descP->readState)) {
-
- /* We can only send the 'close' message to the closer
- * when all requests has been processed!
- */
-
- /* Check "our" queue */
- if (descP->readersQ.first == NULL) {
-
- /* Check "other" queue(s) and if there is a closer pid */
- if ((descP->writersQ.first == NULL) &&
- (descP->acceptorsQ.first == NULL)) {
-
- esaio_stop(env, descP);
-
- }
- }
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
-
- }
- FREE_BIN( &opDataP->buf );
MUNLOCK(descP->writeMtx);
MUNLOCK(descP->readMtx);
break;
@@ -7966,36 +8305,9 @@ BOOLEAN_T esaio_completion_recvfrom(ESAIOThreadData* dataP,
"esaio_completion_recvfrom(%d) -> operation unknown failure"
"\r\n", descP->sock) );
MLOCK(descP->readMtx);
- /* We do not know what this is
- * but we can "assume" that the request failed so we need to
- * remove it from the "queue" if its still there...
- * And cleanup...
- */
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
-
- reason = MKT2(env,
- esock_atom_get_overlapped_result,
- ENO2T(env, error));
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
- esaio_completion_recvfrom_fail(env, descP, error, FALSE);
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
- } else {
- esaio_completion_recvfrom_fail(env, descP, error, TRUE);
- }
- FREE_BIN( &opDataP->buf );
+ esaio_completion_recvfrom_failure(env, descP, opCaller, opDataP, error);
+
MUNLOCK(descP->readMtx);
break;
}
@@ -8015,6 +8327,250 @@ BOOLEAN_T esaio_completion_recvfrom(ESAIOThreadData* dataP,
}
+static
+void esaio_completion_recvfrom_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvFrom* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+ if (IS_OPEN(descP->readState)) {
+ esaio_completion_recvfrom_completed(env, descP,
+ ovl, opEnv, opCaller,
+ opDataP, &req);
+ } else {
+ /* A completed (active) request for a socket that is not open.
+ * Is this even possible?
+ * A race (completed just as the socket was closed).
+ */
+ esaio_completion_recv_not_active(descP);
+ FREE_BIN( &opDataP->buf );
+ }
+
+ } else {
+ /* Request was actually completed directly
+ * (and was therefor not put into the "queue")
+ * => Nothing to do here, other than cleanup (see below).
+ * => But we do not free the "buffer" since it was "used up"
+ * when we (as assumed) got the result (directly)...
+ */
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvfrom_success(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+static
+void esaio_completion_recvfrom_more_data(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvFrom* opDataP,
+ int error)
+{
+ ESockRequestor req;
+
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+ if (IS_OPEN(descP->readState)) {
+ /* We do not actually need to call this function
+ * since we already know its 'more_data', but just
+ * get the same format...
+ */
+ ERL_NIF_TERM reason = MKT2(env,
+ esock_atom_completion_status,
+ ENO2T(env, error));
+ ERL_NIF_TERM completionStatus = esock_make_error(env, reason);
+ ERL_NIF_TERM completionInfo = MKT2(opEnv,
+ opDataP->recvRef,
+ completionStatus);
+
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvfrom_more_data(%d) -> "
+ "send completion message: "
+ "\r\n Completion Status: %T"
+ "\r\n", descP->sock, completionStatus) );
+
+ /* Send a 'recvfrom' completion message */
+ esaio_send_completion_msg(env, // Send env
+ descP, // Descriptor
+ opCaller, // Msg destination
+ opEnv, // Msg env
+ opDataP->sockRef, // Dest socket
+ completionInfo); // Info
+
+ }
+
+ FREE_BIN( &opDataP->buf );
+
+ } else {
+ /* Request was actually completed directly
+ * (and was therefor not put into the "queue")
+ * => Nothing to do here, other than cleanup (see below).
+ * => But we do not free the "buffer" since it was "used up"
+ * when we (as assumed) got the result (directly)...
+ */
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvfrom_more_data(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+/* *** esaio_completion_recvfrom_aborted ***
+ * The only thing *we* do that could cause an abort is the
+ * 'CancelIoEx' call, which we do when closing the socket
+ * (or cancel a request).
+ * But if we have done that;
+ * - Socket state will not be 'open' and
+ * - we have also set closer (pid and ref).
+ */
+static
+void esaio_completion_recvfrom_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvFrom* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+
+ ERL_NIF_TERM reason = esock_atom_closed;
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+
+ /* The socket not being open (assumed closing),
+ * means we are in the closing phase...
+ */
+ if (! IS_OPEN(descP->readState)) {
+
+ /* We can only send the 'close' message to the closer
+ * when all requests has been processed!
+ */
+
+ /* Check "our" queue */
+ if (descP->readersQ.first == NULL) {
+
+ /* Check "other" queue(s) and if there is a closer pid */
+ if ((descP->writersQ.first == NULL) &&
+ (descP->acceptorsQ.first == NULL)) {
+
+ esaio_stop(env, descP);
+
+ }
+ }
+ }
+ }
+
+ FREE_BIN( &opDataP->buf );
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvfrom_aborted(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+/* *** esaio_completion_recvfrom_failure *
+ * A "general" failure happened while performing the 'recvfrom' operation.
+ */
+static
+void esaio_completion_recvfrom_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvFrom* opDataP,
+ int error)
+{
+ ESockRequestor req;
+ ERL_NIF_TERM reason;
+
+ /* We do not know what this is
+ * but we can "assume" that the request failed so we need to
+ * remove it from the "queue" if its still there...
+ * And cleanup...
+ */
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+
+ reason = MKT2(env,
+ esock_atom_completion_status,
+ ENO2T(env, error));
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+ esaio_completion_recvfrom_fail(env, descP, error, FALSE);
+
+ } else {
+ esaio_completion_recvfrom_fail(env, descP, error, TRUE);
+ }
+
+ FREE_BIN( &opDataP->buf );
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvfrom_failure(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
/* *** esaio_completion_recvfrom_completed ***
* The recvfrom request has completed.
@@ -8329,40 +8885,10 @@ BOOLEAN_T esaio_completion_recvmsg(ESAIOThreadData* dataP,
descP->sock,
opDataP->recvRef, MKPID(env, opCaller)) );
MLOCK(descP->readMtx);
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
- if (IS_OPEN(descP->readState)) {
- esaio_completion_recvmsg_completed(env, descP,
- ovl, opEnv, opCaller,
- opDataP,
- &req);
- } else {
- /* A completed (active) request for a socket that is not open.
- * Is this even possible?
- * A race (completed just as the socket was closed).
- */
- esaio_completion_recv_not_active(descP);
- FREE_BIN( &opDataP->data[0] );
- FREE_BIN( &opDataP->ctrl );
- }
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
+ esaio_completion_recvmsg_success(env, descP, ovl, opEnv,
+ opCaller, opDataP);
- } else {
- /* Request was actually completed directly
- * (and was therefor not put into the "queue")
- * => Nothing to do here, other than cleanup (see below).
- * => But we do not free the "buffer" since it was "used up"
- * when we (as assumed) got the result (directly)...
- */
- }
MUNLOCK(descP->readMtx);
break;
@@ -8374,57 +8900,9 @@ BOOLEAN_T esaio_completion_recvmsg(ESAIOThreadData* dataP,
/* *** SAME MTX LOCK ORDER FOR ALL OPs *** */
MLOCK(descP->readMtx);
MLOCK(descP->writeMtx);
- /* The only thing *we* do that could cause an abort is the
- * 'CancelIoEx' call, which we do when closing the socket
- * (or cancel a request).
- * But if we have done that;
- * - Socket state will not be 'open' and
- * - we have also set closer (pid and ref).
- */
-
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
-
- reason = esock_atom_closed,
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
+ esaio_completion_recvmsg_aborted(env, descP, opCaller, opDataP);
- /* The socket not being open (assumed closing),
- * means we are in the closing phase...
- */
- if (! IS_OPEN(descP->readState)) {
-
- /* We can only send the 'close' message to the closer
- * when all requests has been processed!
- */
-
- /* Check "our" queue */
- if (descP->readersQ.first == NULL) {
-
- /* Check "other" queue(s) and if there is a closer pid */
- if ((descP->writersQ.first == NULL) &&
- (descP->acceptorsQ.first == NULL)) {
-
- esaio_stop(env, descP);
-
- }
- }
- }
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
-
- }
- FREE_BIN( &opDataP->data[0] );
- FREE_BIN( &opDataP->ctrl );
MUNLOCK(descP->writeMtx);
MUNLOCK(descP->readMtx);
break;
@@ -8432,40 +8910,12 @@ BOOLEAN_T esaio_completion_recvmsg(ESAIOThreadData* dataP,
default:
SSDBG( descP,
("WIN-ESAIO",
- "esaio_completion_recvmsg(%d) -> operation unknown failure"
+ "esaio_completion_recvmsg(%d) -> unknown operation failure"
"\r\n", descP->sock) );
MLOCK(descP->readMtx);
- /* We do not know what this is
- * but we can "assume" that the request failed so we need to
- * remove it from the "queue" if its still there...
- * And cleanup...
- */
- if (esock_reader_get(env, descP,
- &opDataP->recvRef,
- opCaller,
- &req)) {
-
- reason = MKT2(env,
- esock_atom_get_overlapped_result,
- ENO2T(env, error));
-
- /* Inform the user waiting for a reply */
- esock_send_abort_msg(env, descP, opDataP->sockRef,
- &req, reason);
- esaio_completion_recvmsg_fail(env, descP, error, FALSE);
-
- /* *Maybe* update socket (write) state
- * (depends on if the queue is now empty)
- */
- if (descP->readersQ.first == NULL) {
- descP->readState &= ~ESOCK_STATE_SELECTED;
- }
- } else {
- esaio_completion_recvmsg_fail(env, descP, error, TRUE);
- }
- FREE_BIN( &opDataP->data[0] );
- FREE_BIN( &opDataP->ctrl );
+ esaio_completion_recvmsg_failure(env, descP, opCaller, opDataP, error);
+
MUNLOCK(descP->readMtx);
break;
}
@@ -8487,6 +8937,184 @@ BOOLEAN_T esaio_completion_recvmsg(ESAIOThreadData* dataP,
}
+static
+void esaio_completion_recvmsg_success(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ OVERLAPPED* ovl,
+ ErlNifEnv* opEnv,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvMsg* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+ if (IS_OPEN(descP->readState)) {
+ esaio_completion_recvmsg_completed(env, descP, ovl, opEnv,
+ opCaller, opDataP,
+ &req);
+ } else {
+ /* A completed (active) request for a socket that is not open.
+ * Is this even possible?
+ * A race (completed just as the socket was closed).
+ */
+ esaio_completion_recv_not_active(descP);
+ FREE_BIN( &opDataP->data[0] );
+ FREE_BIN( &opDataP->ctrl );
+ }
+
+ } else {
+ /* Request was actually completed directly
+ * (and was therefor not put into the "queue")
+ * => Nothing to do here, other than cleanup (see below).
+ * => But we do not free the "buffer" since it was "used up"
+ * when we (as assumed) got the result (directly)...
+ */
+ }
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvmsg_success(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+/* *** esaio_completion_recvmsg_aborted ***
+ * The only thing *we* do that could cause an abort is the
+ * 'CancelIoEx' call, which we do when closing the socket
+ * (or cancel a request).
+ * But if we have done that;
+ * - Socket state will not be 'open' and
+ * - we have also set closer (pid and ref).
+ */
+
+static
+void esaio_completion_recvmsg_aborted(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvMsg* opDataP)
+{
+ ESockRequestor req;
+
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+
+ ERL_NIF_TERM reason = esock_atom_closed;
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+
+ /* The socket not being open (assumed closing),
+ * means we are in the closing phase...
+ */
+ if (! IS_OPEN(descP->readState)) {
+
+ /* We can only send the 'close' message to the closer
+ * when all requests has been processed!
+ */
+
+ /* Check "our" queue */
+ if (descP->readersQ.first == NULL) {
+
+ /* Check "other" queue(s) and if there is a closer pid */
+ if ((descP->writersQ.first == NULL) &&
+ (descP->acceptorsQ.first == NULL)) {
+
+ esaio_stop(env, descP);
+
+ }
+ }
+ }
+
+ }
+
+ FREE_BIN( &opDataP->data[0] );
+ FREE_BIN( &opDataP->ctrl );
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvmsg_aborted(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
+
+/* *** esaio_completion_recvmsg_failure *
+ * A "general" failure happened while performing the 'recvmsg' operation.
+ */
+static
+void esaio_completion_recvmsg_failure(ErlNifEnv* env,
+ ESockDescriptor* descP,
+ ErlNifPid* opCaller,
+ ESAIOOpDataRecvMsg* opDataP,
+ int error)
+{
+ ESockRequestor req;
+ ERL_NIF_TERM reason;
+
+ /* We do not know what this is
+ * but we can "assume" that the request failed so we need to
+ * remove it from the "queue" if its still there...
+ * And cleanup...
+ */
+ if (esock_reader_get(env, descP,
+ &opDataP->recvRef,
+ opCaller,
+ &req)) {
+
+ reason = MKT2(env,
+ esock_atom_completion_status,
+ ENO2T(env, error));
+
+ /* Inform the user waiting for a reply */
+ esock_send_abort_msg(env, descP, opDataP->sockRef,
+ &req, reason);
+ esaio_completion_recvmsg_fail(env, descP, error, FALSE);
+
+ } else {
+ esaio_completion_recvmsg_fail(env, descP, error, TRUE);
+ }
+
+ FREE_BIN( &opDataP->data[0] );
+ FREE_BIN( &opDataP->ctrl );
+
+ /* *Maybe* update socket (write) state
+ * (depends on if the queue is now empty)
+ */
+ SSDBG( descP,
+ ("WIN-ESAIO",
+ "esaio_completion_recvmsg_failure(%d) -> "
+ "maybe (%s) update (read) state (ox%X)\r\n",
+ descP->sock,
+ B2S((descP->readersQ.first == NULL)), descP->readState) );
+ if (descP->readersQ.first == NULL) {
+ descP->readState &= ~ESOCK_STATE_SELECTED;
+ }
+
+}
+
/* *** esaio_completion_recvmsg_completed ***
* The recvmsg request has completed.
@@ -8802,7 +9430,7 @@ void esaio_completion_fail(ErlNifEnv* env,
if (inform)
esock_warning_msg("[WIN-ESAIO] Unknown (%s) operation failure: "
"\r\n Descriptor: %d"
- "\r\n Errno: %T"
+ "\r\n Error: %T"
"\r\n",
opStr, descP->sock, ENO2T(env, error));
@@ -8865,10 +9493,12 @@ void esaio_dtor(ErlNifEnv* env,
* so we must have closed it properly to get here
*/
if (! IS_CLOSED(descP->readState) )
- esock_warning_msg("Socket Read State not CLOSED at dtor\r\n");
+ esock_warning_msg("Socket Read State not CLOSED (0x%X) "
+ "at dtor\r\n", descP->readState);
if (! IS_CLOSED(descP->writeState) )
- esock_warning_msg("Socket Write State not CLOSED at dtor\r\n");
+ esock_warning_msg("Socket Write State not CLOSED (0x%X) "
+ "at dtor\r\n", descP->writeState);
if ( descP->sock != INVALID_SOCKET )
esock_warning_msg("Socket %d still valid\r\n", descP->sock);
@@ -8949,7 +9579,21 @@ void esaio_stop(ErlNifEnv* env,
err = esock_close_socket(env, descP, FALSE);
- if (err != 0)
+ switch (err) {
+ case NO_ERROR:
+ break;
+ case WSAENOTSOCK:
+ if (descP->sock != INVALID_SOCKET)
+ esock_warning_msg("[WIN-ESAIO] Attempt to close an "
+ "already closed socket"
+ "\r\n(without a closer process): "
+ "\r\n Controlling Process: %T"
+ "\r\n socket fd: %d"
+ "\r\n",
+ descP->ctrlPid, descP->sock);
+ break;
+
+ default:
esock_warning_msg("[WIN-ESAIO] Failed closing socket without "
"closer process: "
"\r\n Controlling Process: %T"
@@ -8957,6 +9601,9 @@ void esaio_stop(ErlNifEnv* env,
"\r\n Errno: %T"
"\r\n",
descP->ctrlPid, descP->sock, ENO2T(env, err));
+ break;
+ }
+
}
SSDBG( descP,
@@ -9598,3 +10245,6 @@ ERL_NIF_TERM mk_completion_msg(ErlNifEnv* env,
return esock_mk_socket_msg(env, sockRef,
esock_atom_completion, info);
}
+
+
+#endif
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index c93c0dc5cc..3614aecd17 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -281,7 +281,7 @@ ERTS_GLB_INLINE ErtsSysPerfCounter erts_sys_perf_counter(void);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_FORCE_INLINE ErtsSysPerfCounter
-erts_sys_perf_counter()
+erts_sys_perf_counter(void)
{
return (*erts_sys_time_data__.r.o.perf_counter)();
}
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 3bed966864..210d7a5543 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -1061,7 +1061,7 @@ init_smp_sig_notify(void)
{
erts_thr_opts_t thr_opts = ERTS_THR_OPTS_DEFAULT_INITER;
thr_opts.detached = 1;
- thr_opts.name = "sys_sig_dispatcher";
+ thr_opts.name = "erts_ssig_disp";
if (pipe(sig_notify_fds) < 0) {
erts_exit(ERTS_ABORT_EXIT,
@@ -1111,7 +1111,7 @@ erts_sys_main_thread(void)
#else
/* Become signal receiver thread... */
#ifdef ERTS_ENABLE_LOCK_CHECK
- erts_lc_set_thread_name("signal_receiver");
+ erts_lc_set_thread_name("main");
#endif
#endif
smp_sig_notify(0); /* Notify initialized */
diff --git a/erts/emulator/sys/unix/sys_env.c b/erts/emulator/sys/unix/sys_env.c
index 4d8301f985..eb98e7b635 100644
--- a/erts/emulator/sys/unix/sys_env.c
+++ b/erts/emulator/sys/unix/sys_env.c
@@ -16,7 +16,7 @@ extern char **environ;
static void import_initial_env(void);
-void erts_sys_env_init() {
+void erts_sys_env_init(void) {
erts_rwmtx_init(&sysenv_rwmtx, "environ", NIL,
ERTS_LOCK_FLAGS_PROPERTY_STATIC | ERTS_LOCK_FLAGS_CATEGORY_GENERIC);
@@ -24,21 +24,21 @@ void erts_sys_env_init() {
import_initial_env();
}
-const erts_osenv_t *erts_sys_rlock_global_osenv() {
+const erts_osenv_t *erts_sys_rlock_global_osenv(void) {
erts_rwmtx_rlock(&sysenv_rwmtx);
return &sysenv_global_env;
}
-erts_osenv_t *erts_sys_rwlock_global_osenv() {
+erts_osenv_t *erts_sys_rwlock_global_osenv(void) {
erts_rwmtx_rwlock(&sysenv_rwmtx);
return &sysenv_global_env;
}
-void erts_sys_rwunlock_global_osenv() {
+void erts_sys_rwunlock_global_osenv(void) {
erts_rwmtx_rwunlock(&sysenv_rwmtx);
}
-void erts_sys_runlock_global_osenv() {
+void erts_sys_runlock_global_osenv(void) {
erts_rwmtx_runlock(&sysenv_rwmtx);
}
diff --git a/erts/emulator/test/bs_utf_SUITE.erl b/erts/emulator/test/bs_utf_SUITE.erl
index 9e2699119b..4a16ef44ab 100644
--- a/erts/emulator/test/bs_utf_SUITE.erl
+++ b/erts/emulator/test/bs_utf_SUITE.erl
@@ -356,6 +356,10 @@ utf32_illegal_sequences(Config) when is_list(Config) ->
utf32_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large.
utf32_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16.
utf32_fail_range(-100, -1),
+
+ <<>> = id(<< 0 || <<X/utf32>> <= <<"àxxx">>, _ = X >>),
+ <<>> = id(<< 0 || <<X/little-utf32>> <= <<"àxxx">>, _ = X >>),
+
ok.
utf32_fail_range(Char, End) when Char =< End ->
diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl
index 306c1193b0..55bc6eb06b 100644
--- a/erts/emulator/test/decode_packet_SUITE.erl
+++ b/erts/emulator/test/decode_packet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl
index f7fa527bd5..d577f2a1e5 100644
--- a/erts/emulator/test/distribution_SUITE.erl
+++ b/erts/emulator/test/distribution_SUITE.erl
@@ -84,7 +84,9 @@
dyn_node_name_monitor/1,
async_dist_flag/1,
async_dist_port_dctrlr/1,
- async_dist_proc_dctrlr/1]).
+ async_dist_proc_dctrlr/1,
+ creation_selection/1,
+ creation_selection_test/1]).
%% Internal exports.
-export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0,
@@ -118,7 +120,7 @@ all() ->
start_epmd_false, no_epmd, epmd_module, system_limit,
hopefull_data_encoding, hopefull_export_fun_bug,
huge_iovec, is_alive, dyn_node_name_monitor_node, dyn_node_name_monitor,
- {group, async_dist}].
+ {group, async_dist}, creation_selection].
groups() ->
[{bulk_send, [], [bulk_send_small, bulk_send_big, bulk_send_bigbig]},
@@ -520,9 +522,6 @@ nodes2(Config) when is_list(Config) ->
end,
ok.
-id(X) ->
- X.
-
%% Test optimistic distribution flags toward pending connections (DFLAG_DIST_HOPEFULLY)
optimistic_dflags(Config) when is_list(Config) ->
{ok, PeerSender, _Sender} = ?CT_PEER(#{connection => 0, args => ["-setcookie", "NONE"]}),
@@ -3631,8 +3630,126 @@ async_dist_test(Node) ->
ok.
+creation_selection(Config) when is_list(Config) ->
+ register(creation_selection_test_supervisor, self()),
+ Name = atom_to_list(?FUNCTION_NAME) ++ "-"
+ ++ integer_to_list(erlang:system_time()),
+ Host = hostname(),
+ Cmd = lists:append(
+ [ct:get_progname(),
+ " -noshell",
+ " -setcookie ", atom_to_list(erlang:get_cookie()),
+ " -pa ", filename:dirname(code:which(?MODULE)),
+ " -s ", atom_to_list(?MODULE), " ",
+ " creation_selection_test ", atom_to_list(node()), " ",
+ atom_to_list(net_kernel:longnames()), " ", Name, " ", Host]),
+ ct:pal("Node command: ~p~n", [Cmd]),
+ Port = open_port({spawn, Cmd}, [exit_status]),
+ Node = list_to_atom(lists:append([Name, "@", Host])),
+ ok = receive_creation_selection_info(Port, Node).
+
+receive_creation_selection_info(Port, Node) ->
+ receive
+ {creation_selection_test, Node, Creations, InvalidCreation,
+ ClashResolvedCreation} = Msg ->
+ ct:log("Test result: ~p~n", [Msg]),
+ %% Verify that creation values are created as expected. The
+ %% list of creations is in reverse start order...
+ MaxC = (1 bsl 32) - 1,
+ MinC = 4,
+ StartOrderCreations = lists:reverse(Creations),
+ InvalidCreation = lists:foldl(fun (C, C) when is_integer(C),
+ MinC =< C,
+ C =< MaxC ->
+ %% Return next expected
+ %% creation...
+ if C == MaxC -> MinC;
+ true -> C+1
+ end
+ end,
+ hd(StartOrderCreations),
+ StartOrderCreations),
+ false = lists:member(ClashResolvedCreation, [InvalidCreation
+ | Creations]),
+ receive
+ {Port, {exit_status, 0}} ->
+ Port ! {self(), close},
+ ok;
+ {Port, {exit_status, EStat}} ->
+ ct:fail({"node exited abnormally: ", EStat})
+ end;
+ {Port, {exit_status, EStat}} ->
+ ct:fail({"node prematurely exited: ", EStat});
+ {Port, {data, Data}} ->
+ ct:log("~ts", [Data]),
+ receive_creation_selection_info(Port, Node)
+ end,
+ ok.
+
+creation_selection_test([TestSupNode, LongNames, Name, Host]) ->
+ try
+ StartArgs = [Name,
+ case LongNames of
+ true -> longnames;
+ false -> shortnames
+ end],
+ Node = list_to_atom(lists:append([atom_to_list(Name),
+ "@", atom_to_list(Host)])),
+ GoDistributed = fun (F) ->
+ {ok, _} = net_kernel:start(StartArgs),
+ Node = node(),
+ Creation = erlang:system_info(creation),
+ _ = F(Creation),
+ net_kernel:stop(),
+ Creation
+ end,
+ %% We start multiple times to verify that the creation values
+ %% we get from epmd are delivered in sequence. This is a
+ %% must for the test case such as it is written now, but can be
+ %% changed. If changed, this test case must be updated...
+ {Creations,
+ LastCreation} = lists:foldl(fun (_, {Cs, _LC}) ->
+ CFun = fun (X) -> X end,
+ C = GoDistributed(CFun),
+ {[C|Cs], C}
+ end, {[], 0}, lists:seq(1, 5)),
+ %% We create a pid with the creation that epmd will offer us the next
+ %% time we start the distribution and then start the distribution
+ %% once more. The node should avoid this creation, since this would
+ %% cause external identifiers in the system with same
+ %% nodename/creation pair as used by the local node, which in turn
+ %% would cause these identifers not to work as expected. That is, the
+ %% node should silently reject this creation and chose another one when
+ %% starting the distribution.
+ InvalidCreation = LastCreation+1,
+ Pid = erts_test_utils:mk_ext_pid({Node, InvalidCreation}, 4711, 0),
+ true = erts_debug:size(Pid) > 0, %% External pid
+ ResultFun = fun (ClashResolvedCreation) ->
+ pong = net_adm:ping(TestSupNode),
+ Msg = {creation_selection_test, node(), Creations,
+ InvalidCreation, ClashResolvedCreation},
+ {creation_selection_test_supervisor, TestSupNode}
+ ! Msg,
+ %% Wait a bit so the message have time to get
+ %% through before we take down the distribution...
+ receive after 500 -> ok end
+ end,
+ _ = GoDistributed(ResultFun),
+ %% Ensure Pid is not garbage collected before starting the
+ %% distribution...
+ _ = id(Pid),
+ erlang:halt(0)
+ catch
+ Class:Reason:StackTrace ->
+ erlang:display({Class, Reason, StackTrace}),
+ erlang:halt(17)
+ end.
+
%%% Utilities
+id(X) ->
+ X.
+
wait_until(Fun) ->
wait_until(Fun, 24*60*60*1000).
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 030ad5ee13..5d7546c1a4 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -276,6 +276,8 @@ t_build_and_match_literals_large(Config) when is_list(Config) ->
60 = map_size(M0),
60 = maps:size(M0),
+ 60 = apply(erlang, id(map_size), [M0]),
+ 60 = apply(maps, id(size), [M0]),
% with repeating
M1 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
@@ -312,6 +314,8 @@ t_build_and_match_literals_large(Config) when is_list(Config) ->
60 = map_size(M1),
60 = maps:size(M1),
+ 60 = apply(erlang, id(map_size), [M1]),
+ 60 = apply(maps, id(size), [M1]),
% with floats
@@ -365,6 +369,8 @@ t_build_and_match_literals_large(Config) when is_list(Config) ->
90 = map_size(M2),
90 = maps:size(M2),
+ 90 = apply(erlang, id(map_size), [M2]),
+ 90 = apply(maps, id(size), [M2]),
% with bignums
M3 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
@@ -428,6 +434,8 @@ t_build_and_match_literals_large(Config) when is_list(Config) ->
98 = map_size(M3),
98 = maps:size(M3),
+ 98 = apply(erlang, id(map_size), [M3]),
+ 98 = apply(maps, id(size), [M3]),
%% with maps
@@ -548,6 +556,8 @@ t_build_and_match_literals_large(Config) when is_list(Config) ->
95 = map_size(M4),
95 = maps:size(M4),
+ 95 = apply(erlang, id(map_size), [M4]),
+ 95 = apply(maps, id(size), [M4]),
% call for value
@@ -645,6 +655,8 @@ t_build_and_match_literals_large(Config) when is_list(Config) ->
95 = map_size(M5),
95 = maps:size(M5),
+ 95 = apply(erlang, id(map_size), [M5]),
+ 95 = apply(maps, id(size), [M5]),
%% remember
@@ -2220,6 +2232,10 @@ t_bif_map_merge(Config) when is_list(Config) ->
{'EXIT',{{badmap,T},[{maps,merge,_,_}|_]}} =
(catch maps:merge(T, #{})),
{'EXIT',{{badmap,T},[{maps,merge,_,_}|_]}} =
+ (catch maps:merge(M11, T)),
+ {'EXIT',{{badmap,T},[{maps,merge,_,_}|_]}} =
+ (catch maps:merge(T, M11)),
+ {'EXIT',{{badmap,T},[{maps,merge,_,_}|_]}} =
(catch maps:merge(T, T))
end),
ok.
@@ -2462,6 +2478,16 @@ t_bif_erlang_phash2() ->
70249457 = erlang:phash2(M0), % 118679416
59617982 = erlang:phash2(M1), % 51612236
70249457 = erlang:phash2(M2), % 118679416
+
+ M1000 = maps:from_list([{K,K} || K <- lists:seq(1,1000)]),
+ 66609305 = erlang:phash2(M1000),
+
+ Mnested1 = #{flatmap => M0, M0 => flatmap, hashmap => M1000, M1000 => hashmap},
+ 113689339 = erlang:phash2(Mnested1),
+
+ Mnested2 = maps:merge(Mnested1, M1000),
+ 29167443 = erlang:phash2(Mnested2),
+
ok.
t_bif_erlang_phash() ->
@@ -2482,6 +2508,16 @@ t_bif_erlang_phash() ->
2620391445 = erlang:phash(M0,Sz), % 3590546636
1670235874 = erlang:phash(M1,Sz), % 4066388227
2620391445 = erlang:phash(M2,Sz), % 3590546636
+
+ M1000 = maps:from_list([{K,K} || K <- lists:seq(1,1000)]),
+ 1945662653 = erlang:phash(M1000, Sz),
+
+ Mnested1 = #{flatmap => M0, M0 => flatmap, hashmap => M1000, M1000 => hashmap},
+ 113694495 = erlang:phash(Mnested1, Sz),
+
+ Mnested2 = maps:merge(Mnested1, M1000),
+ 431825783 = erlang:phash(Mnested2, Sz),
+
ok.
t_map_encode_decode(Config) when is_list(Config) ->
@@ -2957,25 +2993,31 @@ t_maps_without(_Config) ->
%% Verify that the the number of nodes in hashmaps
%% of different types and sizes does not deviate too
%% much from the theoretical model.
+%% For debug with DBG_HASHMAP_COLLISION_BONANZA the test will expect
+%% the hashmaps to NOT be well balanced.
t_hashmap_balance(_Config) ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ ExpectBalance = not erts_debug:get_internal_state(hashmap_collision_bonanza),
+ hashmap_balance(ExpectBalance),
+ erts_debug:set_internal_state(available_internal_state, false),
+ ok.
+
+hashmap_balance(EB) ->
io:format("Integer keys\n", []),
- hashmap_balance(fun(I) -> I end),
+ hashmap_balance(fun(I) -> I end, EB),
io:format("Float keys\n", []),
- hashmap_balance(fun(I) -> float(I) end),
+ hashmap_balance(fun(I) -> float(I) end, EB),
io:format("String keys\n", []),
- hashmap_balance(fun(I) -> integer_to_list(I) end),
+ hashmap_balance(fun(I) -> integer_to_list(I) end, EB),
io:format("Binary (big) keys\n", []),
- hashmap_balance(fun(I) -> <<I:16/big>> end),
+ hashmap_balance(fun(I) -> <<I:16/big>> end, EB),
io:format("Binary (little) keys\n", []),
- hashmap_balance(fun(I) -> <<I:16/little>> end),
+ hashmap_balance(fun(I) -> <<I:16/little>> end, EB),
io:format("Atom keys\n", []),
- erts_debug:set_internal_state(available_internal_state, true),
- hashmap_balance(fun(I) -> erts_debug:get_internal_state({atom,I}) end),
- erts_debug:set_internal_state(available_internal_state, false),
-
+ hashmap_balance(fun(I) -> erts_debug:get_internal_state({atom,I}) end, EB),
ok.
-hashmap_balance(KeyFun) ->
+hashmap_balance(KeyFun, ExpectBalance) ->
%% For uniformly distributed hash values, the average number of nodes N
%% in a hashmap varies between 0.3*K and 0.4*K where K is number of keys.
%% The standard deviation of N is about sqrt(K)/3.
@@ -3019,9 +3061,10 @@ hashmap_balance(KeyFun) ->
erts_debug:flat_size(MaxMap)])
end,
- true = (MaxDiff < 6), % The probability of this line failing is about 0.000000001
- % for a uniform hash. I've set the probability this "high" for now
- % to detect flaws in our make_internal_hash.
+ %% The probability of this line failing is about 0.000000001
+ %% for a uniform hash. I've set the probability this "high" for now
+ %% to detect flaws in our make_internal_hash.
+ ExpectBalance = (MaxDiff < 6),
ok.
hashmap_nodes(M) ->
@@ -3030,6 +3073,7 @@ hashmap_nodes(M) ->
case element(1,Tpl) of
bitmaps -> Acc + element(2,Tpl);
arrays -> Acc + element(2,Tpl);
+ collisions -> Acc + element(2,Tpl);
_ -> Acc
end
end,
@@ -3232,7 +3276,7 @@ t_dets(_Config) ->
t_tracing(_Config) ->
- dbg:stop_clear(),
+ dbg:stop(),
{ok,Tracer} = dbg:tracer(process,{fun trace_collector/2, self()}),
dbg:p(self(),c),
@@ -3285,7 +3329,7 @@ t_tracing(_Config) ->
%% Check to extra messages
timeout = getmsg(Tracer),
- dbg:stop_clear(),
+ dbg:stop(),
ok.
getmsg(_Tracer) ->
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index f6c6526f54..d28c4d15db 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -95,6 +95,8 @@
alias_bif/1,
monitor_alias/1,
spawn_monitor_alias/1,
+ demonitor_aliasmonitor/1,
+ down_aliasmonitor/1,
monitor_tag/1,
no_pid_wrap/1]).
@@ -184,7 +186,8 @@ groups() ->
gc_request_when_gc_disabled, gc_request_blast_when_gc_disabled,
otp_16436, otp_16642]},
{alias, [],
- [alias_bif, monitor_alias, spawn_monitor_alias]}].
+ [alias_bif, monitor_alias, spawn_monitor_alias,
+ demonitor_aliasmonitor, down_aliasmonitor]}].
init_per_suite(Config) ->
A0 = case application:start(sasl) of
@@ -5025,6 +5028,51 @@ spawn_monitor_alias_test(Peer, Node, SpawnType, ExitReason) ->
ok
end.
+demonitor_aliasmonitor(Config) when is_list(Config) ->
+ {ok, Peer, Node} = ?CT_PEER(),
+ Fun = fun () ->
+ receive
+ {alias, Alias} ->
+ Alias ! {alias_reply, Alias, self()}
+ end
+ end,
+ LPid = spawn(Fun),
+ RPid = spawn(Node, Fun),
+ AliasMonitor = erlang:monitor(process, LPid, [{alias, explicit_unalias}]),
+ erlang:demonitor(AliasMonitor),
+ LPid ! {alias, AliasMonitor},
+ receive {alias_reply, AliasMonitor, LPid} -> ok end,
+ %% Demonitor signal has been received and cleaned up. Cleanup of
+ %% it erroneously removed it from the alias table which caused
+ %% remote use of the alias to stop working...
+ RPid ! {alias, AliasMonitor},
+ receive {alias_reply, AliasMonitor, RPid} -> ok end,
+ exit(LPid, kill),
+ peer:stop(Peer),
+ false = is_process_alive(LPid),
+ ok.
+
+down_aliasmonitor(Config) when is_list(Config) ->
+ {ok, Peer, Node} = ?CT_PEER(),
+ LPid = spawn(fun () -> receive infinty -> ok end end),
+ RPid = spawn(Node,
+ fun () ->
+ receive
+ {alias, Alias} ->
+ Alias ! {alias_reply, Alias, self()}
+ end
+ end),
+ AliasMonitor = erlang:monitor(process, LPid, [{alias, explicit_unalias}]),
+ exit(LPid, bye),
+ receive {'DOWN', AliasMonitor, process, LPid, bye} -> ok end,
+ %% Down signal has been received and cleaned up. Cleanup of
+ %% it erroneously removed it from the alias table which caused
+ %% remote use of the alias to stop working...
+ RPid ! {alias, AliasMonitor},
+ receive {alias_reply, AliasMonitor, RPid} -> ok end,
+ peer:stop(Peer),
+ ok.
+
monitor_tag(Config) when is_list(Config) ->
%% Exit signals with immediate exit reasons are sent
%% in a different manner than compound exit reasons, and
diff --git a/erts/emulator/utils/make_driver_tab b/erts/emulator/utils/make_driver_tab
index 4ed9cb0ce8..0749df1cbe 100755
--- a/erts/emulator/utils/make_driver_tab
+++ b/erts/emulator/utils/make_driver_tab
@@ -107,7 +107,7 @@ foreach (@static_drivers) {
}
print " {NULL}\n};\n";
-print "void erts_init_static_drivers() {\n";
+print "void erts_init_static_drivers(void) {\n";
my $index = 0;
foreach (@static_drivers) {
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index 18a589ac27..7613533bdd 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -745,12 +745,7 @@ static unsigned int get_creation(Node* node)
/* buf is actually one byte larger than bsize,
giving place for null termination */
-static void do_request(g, fd, s, buf, bsize)
- EpmdVars *g;
- int fd;
- Connection *s;
- char *buf;
- int bsize;
+static void do_request(EpmdVars *g, int fd, Connection *s, char *buf, int bsize)
{
char wbuf[OUTBUF_SIZE]; /* Buffer for writing */
int i;
diff --git a/erts/etc/common/escript.c b/erts/etc/common/escript.c
index fe474338fb..c7418b2ace 100644
--- a/erts/etc/common/escript.c
+++ b/erts/etc/common/escript.c
@@ -286,7 +286,7 @@ find_prog(char *origpath)
beg = end + 1;
continue;
}
- strncpy(dir, beg, sz);
+ memcpy(dir, beg, sz);
dir[sz] = '\0';
beg = end + 1;
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index 297e41dca2..f45c18f3e6 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -354,8 +354,7 @@ int main(int argc, char **argv) {
* message loop
*/
static int
-message_loop(erlin_fd, erlout_fd)
- int erlin_fd, erlout_fd;
+message_loop(int erlin_fd, int erlout_fd)
{
int i;
time_t now, last_received;
@@ -776,8 +775,7 @@ int wait_until_close_write_or_env_tmo(int tmo) {
* Sends an HEART_ACK.
*/
static int
-notify_ack(fd)
- int fd;
+notify_ack(int fd)
{
struct msg m;
@@ -824,9 +822,7 @@ heart_cmd_reply(int fd, char *s)
* FIXME.
*/
static int
-write_message(fd, mp)
- int fd;
- struct msg *mp;
+write_message(int fd, struct msg *mp)
{
int len = ntohs(mp->len);
@@ -853,9 +849,7 @@ write_message(fd, mp)
* message.
*/
static int
-read_message(fd, mp)
- int fd;
- struct msg *mp;
+read_message(int fd, struct msg *mp)
{
int rlen, i;
unsigned char* tmp;
@@ -891,9 +885,7 @@ read_message(fd, mp)
* bytes read (i.e. len) , 0 if eof, or < 0 if error. len must be > 0.
*/
static int
-read_fill(fd, buf, len)
- int fd, len;
- char *buf;
+read_fill(int fd, char *buf, int len)
{
int i, got = 0;
@@ -914,9 +906,7 @@ read_fill(fd, buf, len)
* 0 if eof, or < 0 if error. len > maxlen > 0 must hold.
*/
static int
-read_skip(fd, buf, maxlen, len)
- int fd, maxlen, len;
- char *buf;
+read_skip(int fd, char *buf, int maxlen, int len)
{
int i, got = 0;
char c;
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 460849ef2f..e1aa6d4126 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -497,10 +497,11 @@ typedef struct {
typedef struct {
int detached; /* boolean (default false) */
int suggested_stack_size; /* kilo words (default sys dependent) */
- char *name; /* max 14 char long (default no-name) */
+ char *name; /* max 15 char long (default no-name) */
} ethr_thr_opts;
#define ETHR_THR_OPTS_DEFAULT_INITER {0, -1, NULL}
+#define ETHR_THR_NAME_MAX 15
#if !defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
# define ETHR_NEED_SPINLOCK_PROTOTYPES__
diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c
index b17aa3a17f..da4f1af11d 100644
--- a/erts/lib_src/pthread/ethread.c
+++ b/erts/lib_src/pthread/ethread.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,7 +81,7 @@ typedef struct {
void *prep_func_res;
size_t stacksize;
char *name;
- char name_buff[32];
+ char name_buff[ETHR_THR_NAME_MAX + 1];
} ethr_thr_wrap_data__;
static void *thr_wrapper(void *vtwd)
@@ -334,21 +334,9 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg,
twd.stacksize = 0;
if (opts && opts->name) {
- size_t nlen = sizeof(twd.name_buff);
-#ifdef __HAIKU__
- if (nlen > B_OS_NAME_LENGTH)
- nlen = B_OS_NAME_LENGTH;
-#else
- /*
- * Length of 16 is known to work. At least pthread_setname_np()
- * is documented to fail on too long name string, but documentation
- * does not say what the limit is. Do not have the time to dig
- * further into that now...
- */
- if (nlen > 16)
- nlen = 16;
-#endif
- snprintf(twd.name_buff, nlen, "%s", opts->name);
+ if (strlen(opts->name) >= sizeof(twd.name_buff))
+ return EINVAL;
+ strcpy(twd.name_buff, opts->name);
twd.name = twd.name_buff;
} else
twd.name = NULL;
@@ -506,6 +494,8 @@ ethr_getname(ethr_tid tid, char *buf, size_t len)
void
ethr_setname(char *name)
{
+ if (strlen(name) > ETHR_THR_NAME_MAX)
+ return;
#if defined(ETHR_HAVE_PTHREAD_SETNAME_NP_2)
pthread_setname_np(ethr_self(), name);
#elif defined(ETHR_HAVE_PTHREAD_SET_NAME_NP_2)
diff --git a/erts/preloaded/ebin/prim_socket.beam b/erts/preloaded/ebin/prim_socket.beam
index ba50f42a01..45f5ab71d9 100644
--- a/erts/preloaded/ebin/prim_socket.beam
+++ b/erts/preloaded/ebin/prim_socket.beam
Binary files differ
diff --git a/erts/preloaded/src/prim_socket.erl b/erts/preloaded/src/prim_socket.erl
index fd4432cbc9..8da47bba82 100644
--- a/erts/preloaded/src/prim_socket.erl
+++ b/erts/preloaded/src/prim_socket.erl
@@ -512,8 +512,10 @@ send(SockRef, Bin, EFlags, SendRef) when is_integer(EFlags) ->
{select, Written} ->
<<_:Written/binary, RestBin/binary>> = Bin,
{select, RestBin, EFlags};
- completion ->
- completion;
+
+ completion = C ->
+ C;
+
{error, _Reason} = Result ->
Result
end;
@@ -560,11 +562,13 @@ sendto(SockRef, Bin, To, Flags, SendRef) ->
sockaddr ->
{error, {invalid, {Cause, To}}}
end;
+
ok ->
ok;
{ok, Written} ->
<<_:Written/binary, RestBin/binary>> = Bin,
{ok, RestBin};
+
select ->
Cont = {To, ETo, EFlags},
{select, Cont};
@@ -572,6 +576,10 @@ sendto(SockRef, Bin, To, Flags, SendRef) ->
<<_:Written/binary, RestBin/binary>> = Bin,
Cont = {To, ETo, EFlags},
{select, RestBin, Cont};
+
+ completion = C->
+ C;
+
{error, _Reason} = Result ->
Result
end
diff --git a/erts/test/ethread_SUITE.erl b/erts/test/ethread_SUITE.erl
index 19f738c572..4c2c1139df 100644
--- a/erts/test/ethread_SUITE.erl
+++ b/erts/test/ethread_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,7 +43,8 @@
rwspinlock/1,
rwmutex/1,
atomic/1,
- dw_atomic_massage/1]).
+ dw_atomic_massage/1,
+ thread_name/1]).
-include_lib("common_test/include/ct.hrl").
@@ -65,7 +66,8 @@ all() ->
rwspinlock,
rwmutex,
atomic,
- dw_atomic_massage].
+ dw_atomic_massage,
+ thread_name].
init_per_testcase(Case, Config) ->
case inet:gethostname() of
@@ -158,6 +160,10 @@ atomic(Config) ->
dw_atomic_massage(Config) ->
run_case(Config, "dw_atomic_massage", "").
+%% Tests thread names.
+thread_name(Config) ->
+ run_case(Config, "thread_name", "").
+
%%
%%
%% Auxiliary functions
diff --git a/erts/test/ethread_SUITE_data/ethread_tests.c b/erts/test/ethread_SUITE_data/ethread_tests.c
index 048acd6a95..377aabac24 100644
--- a/erts/test/ethread_SUITE_data/ethread_tests.c
+++ b/erts/test/ethread_SUITE_data/ethread_tests.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@
#define PRINT_VA_LIST(FRMT) \
do { \
- if (FRMT && FRMT != '\0') { \
+ if (FRMT && *(FRMT) != '\0') { \
va_list args; \
va_start(args, FRMT); \
vfprintf(stderr, FRMT, args); \
@@ -1757,6 +1757,7 @@ at_dw_thr(void *vval)
break;
}
}
+ return NULL;
}
static void
@@ -1783,6 +1784,120 @@ dw_atomic_massage_test(void)
}
}
+static ethr_mutex thread_name_mutex;
+static ethr_cond thread_name_cond;
+static int thread_name_state;
+
+static void *
+thread_name_thread(void *my_tid)
+{
+ int res;
+
+ ethr_mutex_lock(&thread_name_mutex);
+ thread_name_state = 1;
+ while (thread_name_state == 1) {
+ res = ethr_cond_wait(&thread_name_cond, &thread_name_mutex);
+ ASSERT(res == 0);
+ }
+ ethr_mutex_unlock(&thread_name_mutex);
+ return NULL;
+}
+
+static void
+thread_name(void)
+{
+ static const ethr_thr_opts default_thr_opts = ETHR_THR_OPTS_DEFAULT_INITER;
+ ethr_tid tid;
+ ethr_thr_opts thr_opts;
+ int res;
+ char buf[ETHR_THR_NAME_MAX + 1];
+
+ res = ethr_mutex_init(&thread_name_mutex);
+ ASSERT(res == 0);
+ res = ethr_cond_init(&thread_name_cond);
+ ASSERT(res == 0);
+
+ if (ethr_getname(ethr_self(), buf, sizeof(buf)) == ENOSYS) {
+ skip("thread names are not supported");
+ return;
+ }
+
+ /* create a thread with the minimum name length */
+ thread_name_state = 0;
+
+ memcpy(&thr_opts, &default_thr_opts, sizeof(thr_opts));
+ thr_opts.name = "";
+ res = ethr_thr_create(&tid, thread_name_thread, NULL, &thr_opts);
+ ASSERT(res == 0);
+
+ memset(buf, 0xFF, sizeof(buf));
+ res = ethr_getname(tid, buf, sizeof(buf));
+ ASSERT(res == 0);
+
+ res = strcmp(buf, "");
+ ASSERT(res == 0);
+
+ ethr_mutex_lock(&thread_name_mutex);
+ thread_name_state = 0;
+ ethr_cond_signal(&thread_name_cond);
+ ethr_mutex_unlock(&thread_name_mutex);
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+
+ /* create a thread with a middling name length */
+ thread_name_state = 0;
+
+ memcpy(&thr_opts, &default_thr_opts, sizeof(thr_opts));
+ thr_opts.name = "123456789";
+ res = ethr_thr_create(&tid, thread_name_thread, NULL, &thr_opts);
+ ASSERT(res == 0);
+
+ memset(buf, 0xFF, sizeof(buf));
+ res = ethr_getname(tid, buf, sizeof(buf));
+ ASSERT(res == 0);
+
+ res = strcmp(buf, "123456789");
+ ASSERT(res == 0);
+
+ ethr_mutex_lock(&thread_name_mutex);
+ thread_name_state = 0;
+ ethr_cond_signal(&thread_name_cond);
+ ethr_mutex_unlock(&thread_name_mutex);
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+
+ /* create a thread with the maximum name length */
+ thread_name_state = 0;
+
+ memcpy(&thr_opts, &default_thr_opts, sizeof(thr_opts));
+ thr_opts.name = "123456789012345";
+ res = ethr_thr_create(&tid, thread_name_thread, NULL, &thr_opts);
+ ASSERT(res == 0);
+
+ memset(buf, 0xFF, sizeof(buf));
+ res = ethr_getname(tid, buf, sizeof(buf));
+ ASSERT(res == 0);
+
+ res = strcmp(buf, "123456789012345");
+ ASSERT(res == 0);
+
+ ethr_mutex_lock(&thread_name_mutex);
+ thread_name_state = 0;
+ ethr_cond_signal(&thread_name_cond);
+ ethr_mutex_unlock(&thread_name_mutex);
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+
+ /* create a thread with an over-sized name length */
+ memcpy(&thr_opts, &default_thr_opts, sizeof(thr_opts));
+ thr_opts.name = "1234567890123456";
+ res = ethr_thr_create(&tid, thread_name_thread, NULL, &thr_opts);
+ ASSERT(res == EINVAL);
+}
+
void *
at_thread(void *unused)
{
@@ -1958,6 +2073,8 @@ main(int argc, char *argv[])
atomic_test();
else if (strcmp(testcase, "dw_atomic_massage") == 0)
dw_atomic_massage_test();
+ else if (strcmp(testcase, "thread_name") == 0)
+ thread_name();
else
skip("Test case \"%s\" not implemented yet", testcase);
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
index 40e2be0a85..a8424ea46f 100644
--- a/erts/test/otp_SUITE.erl
+++ b/erts/test/otp_SUITE.erl
@@ -542,7 +542,7 @@ ignore_undefs() ->
%% The following functions are optional dependencies for diameter
#{{dbg,ctp,0} => true,
{dbg,p,2} => true,
- {dbg,stop_clear,0} => true,
+ {dbg,stop,0} => true,
{dbg,trace_port,2} => true,
{dbg,tracer,2} => true,
{erl_prettypr,format,1} => true,
diff --git a/erts/vsn.mk b/erts/vsn.mk
index c9cabd73d4..67df301d2e 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
#
-VSN = 13.2
+VSN = 13.2.2
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index 8dc0dfedcf..aad9db5289 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -1167,7 +1167,7 @@ static mem_chunk_t *ber_new_chunk(unsigned int length) {
new->next = NULL;
new->top = enif_alloc(sizeof(char) * length);
if (new->top == NULL) {
- free(new);
+ enif_free(new);
return NULL;
}
new->curr = new->top + length - 1;
diff --git a/lib/asn1/test/error_SUITE.erl b/lib/asn1/test/error_SUITE.erl
index cfec438e1b..aa2b36bbd7 100644
--- a/lib/asn1/test/error_SUITE.erl
+++ b/lib/asn1/test/error_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 4ce0d562d3..df12121197 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -3276,7 +3276,7 @@ do_trace(Terms) ->
ok.
stop_trace(true) ->
- dbg:stop_clear();
+ dbg:stop();
stop_trace(false) ->
ok.
diff --git a/lib/compiler/Makefile b/lib/compiler/Makefile
index a7d896f258..9394129f02 100644
--- a/lib/compiler/Makefile
+++ b/lib/compiler/Makefile
@@ -38,6 +38,7 @@ include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=crypto
+NO_TEST_TARGET:=1 # Avoid warning about ignoring old recipe for target 'test'
include $(ERL_TOP)/make/app_targets.mk
# Enable feature maybe_expr in runtime when running tests
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index af671ff7ba..f92505409c 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -32,6 +32,43 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 8.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed type handling bugs that could cause an internal
+ error in the compiler for correct code.</p>
+ <p>
+ Own Id: OTP-18565 Aux Id: GH-7147 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 8.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>When a map update such as <c>#{}#{key:=value}</c> that
+ should fail with an exception was unused, the exception
+ would be lost.</p>
+ <p>
+ Own Id: OTP-18497 Aux Id: GH-6960, PR-6965 </p>
+ </item>
+ <item>
+ <p>Fixed bug in the validator that made it reject valid
+ code.</p>
+ <p>
+ Own Id: OTP-18516 Aux Id: GH-6969 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 8.2.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/.gitignore b/lib/compiler/src/.gitignore
new file mode 100644
index 0000000000..05d4e67134
--- /dev/null
+++ b/lib/compiler/src/.gitignore
@@ -0,0 +1 @@
+OPCODES-GENERATED
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index 82b0a12a7d..e0625337b5 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -157,7 +157,7 @@ docs:
clean:
rm -f $(TARGET_FILES)
- rm -f $(EGEN)/beam_opcodes.erl $(EGEN)/beam_opcodes.hrl
+ rm -f $(EGEN)/beam_opcodes.erl $(EGEN)/beam_opcodes.hrl $(EGEN)/OPCODES-GENERATED
rm -f $(EGEN)/core_parse.erl
rm -f core
diff --git a/lib/compiler/src/beam_bounds.erl b/lib/compiler/src/beam_bounds.erl
index 6f3902596e..6ac5141821 100644
--- a/lib/compiler/src/beam_bounds.erl
+++ b/lib/compiler/src/beam_bounds.erl
@@ -46,7 +46,28 @@
bounds('bnot', R0) ->
case R0 of
- {A,B} ->
+ {A, B} when is_integer(A), is_integer(B), A =/= B ->
+ %% While it's easy to get an exact range, doing so can make certain
+ %% chains of operations slow to converge, e.g.
+ %%
+ %% f(0) -> -1; f(N) -> abs(bnot f(N)).
+ %%
+ %% Where the range increases by 1 every time we pass through,
+ %% making it more or less impossible to reach a fixpoint.
+ %%
+ %% We therefore widen the range a bit quicker to ensure that we
+ %% converge on 'any' within a reasonable time frame, hoping that
+ %% the range will still be tight enough in the cases where we
+ %% don't feed the result into itself.
+ case {abs(A) bsr ?NUM_BITS, abs(B) bsr ?NUM_BITS} of
+ {0, 0} ->
+ Min = min(-B - 1, -(B bsl 1) - 1),
+ Max = max(-A - 1, -(A bsl 1) - 1),
+ normalize({Min, Max});
+ {_, _} ->
+ any
+ end;
+ {A, B} ->
R = {inf_add(inf_neg(B), -1), inf_add(inf_neg(A), -1)},
normalize(R);
_ ->
diff --git a/lib/compiler/src/beam_call_types.erl b/lib/compiler/src/beam_call_types.erl
index 8b9cb836fd..4324080098 100644
--- a/lib/compiler/src/beam_call_types.erl
+++ b/lib/compiler/src/beam_call_types.erl
@@ -364,14 +364,30 @@ types(erlang, is_boolean, [Type]) ->
end;
types(erlang, is_float, [Type]) ->
sub_unsafe_type_test(Type, #t_float{});
-types(erlang, is_function, [Type, #t_integer{elements={Arity,Arity}}])
- when Arity >= 0, Arity =< ?MAX_FUNC_ARGS ->
- RetType =
- case meet(Type, #t_fun{arity=Arity}) of
- Type -> #t_atom{elements=[true]};
- none -> #t_atom{elements=[false]};
- _ -> beam_types:make_boolean()
- end,
+types(erlang, is_function, [Type, ArityType]) ->
+ RetType = case meet(ArityType, #t_integer{}) of
+ none ->
+ none;
+ #t_integer{elements={Arity,Arity}}
+ when is_integer(Arity) ->
+ if
+ Arity < 0 ->
+ none;
+ 0 =< Arity, Arity =< ?MAX_FUNC_ARGS ->
+ case meet(Type, #t_fun{arity=Arity}) of
+ Type -> #t_atom{elements=[true]};
+ none -> #t_atom{elements=[false]};
+ _ -> beam_types:make_boolean()
+ end;
+ Arity > ?MAX_FUNC_ARGS ->
+ #t_atom{elements=[false]}
+ end;
+ #t_integer{} ->
+ case meet(Type, #t_fun{}) of
+ none -> #t_atom{elements=[false]};
+ _ -> beam_types:make_boolean()
+ end
+ end,
sub_unsafe(RetType, [any, any]);
types(erlang, is_function, [Type]) ->
sub_unsafe_type_test(Type, #t_fun{});
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 87cc5e761d..35ba0ba82d 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 90672bab7c..9ae5a33d74 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -464,6 +464,7 @@ add_scope([I|Is], Scope) ->
[I|add_scope(Is, Scope)];
add_scope([], _Scope) -> [].
+is_shareable([{badmatch,_}|_]) -> false;
is_shareable([build_stacktrace|_]) -> false;
is_shareable([{case_end,_}|_]) -> false;
is_shareable([{'catch',_,_}|_]) -> false;
diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl
index 619a9f032a..448b3b4313 100644
--- a/lib/compiler/src/beam_ssa.erl
+++ b/lib/compiler/src/beam_ssa.erl
@@ -383,10 +383,21 @@ successors(#b_blk{last=Terminator}) ->
-spec normalize(b_set() | terminator()) ->
b_set() | terminator().
-normalize(#b_set{op={bif,Bif},args=Args}=Set) ->
+normalize(#b_set{anno=Anno0,op={bif,Bif},args=Args}=Set) ->
case {is_commutative(Bif),Args} of
{true, [#b_literal{}=Lit,#b_var{}=Var]} ->
- Set#b_set{args=[Var,Lit]};
+ Anno = case Anno0 of
+ #{arg_types := ArgTypes0} ->
+ case ArgTypes0 of
+ #{1 := Type} ->
+ Anno0#{arg_types => #{0 => Type}};
+ #{} ->
+ Anno0
+ end;
+ #{} ->
+ Anno0
+ end,
+ Set#b_set{anno=Anno,args=[Var,Lit]};
{_, _} ->
Set
end;
diff --git a/lib/compiler/src/beam_ssa_alias.erl b/lib/compiler/src/beam_ssa_alias.erl
index daa249d629..c16011ebc6 100644
--- a/lib/compiler/src/beam_ssa_alias.erl
+++ b/lib/compiler/src/beam_ssa_alias.erl
@@ -874,12 +874,12 @@ aa_make_fun(Dst, Callee=#b_local{name=#b_literal{}},
%% and ensure that the value is only used once, even if the
%% argument dies at this location.
%%
- %% We also update the call info for the callee in the #aas{} to
- %% reflect the aliased status for the arguments coming from the
- %% environment.
+ %% We also assume that all arguments are aliased because someone
+ %% could have stolen the function through tracing and called it
+ %% with unexpected arguments, which may be aliased.
SS = aa_set_aliased([Dst|Env0], SS0),
#{ Callee := Status0 } = Info0,
- Status = aa_merge_env(reverse(Status0), [aliased || _ <- Env0], []),
+ Status = [aliased || _ <- Status0],
#{ Callee := PrevStatus } = Info0,
Info = Info0#{ Callee := Status },
Repeats = case PrevStatus =/= Status of
@@ -893,13 +893,6 @@ aa_make_fun(Dst, Callee=#b_local{name=#b_literal{}},
AAS = AAS0#aas{call_args=Info,repeats=Repeats},
{SS, AAS}.
-aa_merge_env([_|Args], [E|Env], Acc) ->
- aa_merge_env(Args, Env, [E|Acc]);
-aa_merge_env([Arg|Args], [], Acc) ->
- aa_merge_env(Args, [], [Arg|Acc]);
-aa_merge_env([], [], Acc) ->
- Acc.
-
aa_breadth_first(Funs, FuncDb) ->
IsExported = fun (F) ->
#{ F := #func_info{exported=E} } = FuncDb,
diff --git a/lib/compiler/src/beam_ssa_check.erl b/lib/compiler/src/beam_ssa_check.erl
index 0d3faa0ee2..f344286943 100644
--- a/lib/compiler/src/beam_ssa_check.erl
+++ b/lib/compiler/src/beam_ssa_check.erl
@@ -285,8 +285,9 @@ env_post1(_Pattern, _Actual, _Env) ->
?DP("Failed to match ~p <-> ~p~n", [_Pattern, _Actual]),
error({internal_pattern_match_error,env_post1}).
-post_bitstring(Bytes, Actual, _Env) ->
- Actual = build_bitstring(Bytes, <<>>).
+post_bitstring(Bytes, Actual, Env) ->
+ Actual = build_bitstring(Bytes, <<>>),
+ Env.
%% Convert the parsed literal binary to an actual bitstring.
build_bitstring([{integer,_,V}|Bytes], Acc) ->
diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl
index c4708e9b11..9f6169829b 100644
--- a/lib/compiler/src/beam_ssa_codegen.erl
+++ b/lib/compiler/src/beam_ssa_codegen.erl
@@ -1450,6 +1450,12 @@ cg_copy_1([], _St) -> [].
element(1, Val) =:= atom orelse
element(1, Val) =:= literal)).
+bif_to_test(min, Args, Fail, St) ->
+ %% The min/2 and max/2 BIFs can only be rewritten to tests when
+ %% both arguments are known to be booleans.
+ bif_to_test('and', Args, Fail, St);
+bif_to_test(max, Args, Fail, St) ->
+ bif_to_test('or', Args, Fail, St);
bif_to_test('or', [V1,V2], {f,Lbl}=Fail, St0) when Lbl =/= 0 ->
{SuccLabel,St} = new_label(St0),
{[{test,is_eq_exact,{f,SuccLabel},[V1,{atom,false}]},
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index e3406f12de..dc76755aad 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -680,7 +680,7 @@ sanitize([L|Ls], InBlocks, Count0, Values0, Blocks0) ->
no_change ->
Blk = sanitize_last(Blk0, Values0),
Blocks1 = Blocks0#{L := Blk},
- Blocks = sanitize_reachable(Blk0, Blocks1),
+ Blocks = sanitize_reachable(Blk, Blocks1),
sanitize(Ls, InBlocks, Count0, Values0, Blocks);
{Is,Last,Count,Values} ->
Blk1 = Blk0#b_blk{is=Is,last=Last},
diff --git a/lib/compiler/src/beam_ssa_private_append.erl b/lib/compiler/src/beam_ssa_private_append.erl
index 3f2e3715ec..c295492762 100644
--- a/lib/compiler/src/beam_ssa_private_append.erl
+++ b/lib/compiler/src/beam_ssa_private_append.erl
@@ -86,6 +86,17 @@ find_appends_blk([], _, Found) ->
Found.
find_appends_is([#b_set{dst=Dst, op=bs_create_bin,
+ args=[#b_literal{val=append},
+ _,
+ Lit=#b_literal{val= <<>>}|_]}|Is],
+ Fun, Found0) ->
+ %% Special case for when the first fragment is a literal <<>> as
+ %% it won't be annotated as unique nor will it die with the
+ %% instruction.
+ AlreadyFound = maps:get(Fun, Found0, []),
+ Found = Found0#{Fun => [{append,Dst,Lit}|AlreadyFound]},
+ find_appends_is(Is, Fun, Found);
+find_appends_is([#b_set{dst=Dst, op=bs_create_bin,
args=[#b_literal{val=append},SegmentInfo,Var|_],
anno=#{first_fragment_dies:=Dies}=Anno}|Is],
Fun, Found0) ->
@@ -468,6 +479,16 @@ patch_appends_is([I0=#b_set{dst=Dst}|Rest], PD0, Cnt0, Acc, BlockAdditions0)
Ps = keysort(1, map(ExtractOpargs, Patches)),
{Is, Cnt} = patch_opargs(I0, Ps, Cnt0),
patch_appends_is(Rest, PD, Cnt, Is++Acc, BlockAdditions0);
+ [{append,Dst,#b_literal{val= <<>>}=Lit}] ->
+ %% Special case for when the first fragment is a literal
+ %% <<>> and it has to be replaced with a bs_init_writable.
+ #b_set{op=bs_create_bin,dst=Dst,args=Args0}=I0,
+ [#b_literal{val=append},SegInfo,Lit|OtherArgs] = Args0,
+ {V,Cnt} = new_var(Cnt0),
+ Init = #b_set{op=bs_init_writable,dst=V,args=[#b_literal{val=256}]},
+ I = I0#b_set{args=[#b_literal{val=private_append},
+ SegInfo,V|OtherArgs]},
+ patch_appends_is(Rest, PD, Cnt, [I,Init|Acc], BlockAdditions0);
[{append,Dst,_}] ->
#b_set{op=bs_create_bin,dst=Dst,args=Args0}=I0,
[#b_literal{val=append}|OtherArgs] = Args0,
@@ -565,6 +586,8 @@ patch_literal_term(<<>>, self, Cnt0) ->
{V,Cnt} = new_var(Cnt0),
I = #b_set{op=bs_init_writable,dst=V,args=[#b_literal{val=256}]},
{V, [I], Cnt};
+patch_literal_term(Lit, self, Cnt) ->
+ {#b_literal{val=Lit}, [], Cnt};
patch_literal_term([H0|T0], {hd,Element}, Cnt0) ->
{H,Extra,Cnt1} = patch_literal_term(H0, Element, Cnt0),
{T,[],Cnt1} = patch_literal_term(T0, [], Cnt1),
diff --git a/lib/compiler/src/beam_types.erl b/lib/compiler/src/beam_types.erl
index 9c3da159c4..c3bf7c8fae 100644
--- a/lib/compiler/src/beam_types.erl
+++ b/lib/compiler/src/beam_types.erl
@@ -1179,14 +1179,23 @@ float_from_range(none) ->
none;
float_from_range(any) ->
#t_float{};
-float_from_range({'-inf','+inf'}) ->
- #t_float{};
-float_from_range({'-inf',Max}) ->
- #t_float{elements={'-inf',float(Max)}};
-float_from_range({Min,'+inf'}) ->
- #t_float{elements={float(Min),'+inf'}};
-float_from_range({Min,Max}) ->
- #t_float{elements={float(Min),float(Max)}}.
+float_from_range({Min0,Max0}) ->
+ case {safe_float(Min0),safe_float(Max0)} of
+ {'-inf','+inf'} ->
+ #t_float{};
+ {Min,Max} ->
+ #t_float{elements={Min,Max}}
+ end.
+
+safe_float(N) when is_number(N) ->
+ try
+ float(N)
+ catch
+ error:_ when N < 0 -> '-inf';
+ error:_ when N > 0 -> '+inf'
+ end;
+safe_float('-inf'=NegInf) -> NegInf;
+safe_float('+inf'=PosInf) -> PosInf.
integer_from_range(none) ->
none;
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index f19ea897fe..217b7a2c97 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -1582,7 +1582,7 @@ update_create_bin_list([], Vst) -> Vst.
update_create_bin_type(append) -> #t_bitstring{};
update_create_bin_type(private_append) -> #t_bitstring{};
update_create_bin_type(binary) -> #t_bitstring{};
-update_create_bin_type(float) -> #t_float{};
+update_create_bin_type(float) -> #t_number{};
update_create_bin_type(integer) -> #t_integer{};
update_create_bin_type(utf8) -> #t_integer{};
update_create_bin_type(utf16) -> #t_integer{};
@@ -2830,7 +2830,13 @@ unpack_typed_arg(#tr{r=Reg,t=Type}, Vst) ->
%% The validator is not yet clever enough to do proper range analysis like
%% the main type pass, so our types will be a bit cruder here, but they
%% should at the very least not be in direct conflict.
- true = none =/= beam_types:meet(get_movable_term_type(Reg, Vst), Type),
+ Current = get_movable_term_type(Reg, Vst),
+ case beam_types:meet(Current, Type) of
+ none ->
+ throw({bad_typed_register, Current, Type});
+ _ ->
+ ok
+ end,
Reg;
unpack_typed_arg(Arg, _Vst) ->
Arg.
@@ -3429,7 +3435,17 @@ bif_types(Op, Ss, Vst) ->
Other
end;
{_,_} ->
- beam_call_types:types(erlang, Op, Args)
+ Res0 = beam_call_types:types(erlang, Op, Args),
+ {Ret0, ArgTypes, SubSafe} = Res0,
+
+ %% Match the non-converging range analysis done in
+ %% `beam_ssa_type:opt_ranges/1`. This is safe since the validator
+ %% doesn't have to worry about convergence.
+ case beam_call_types:arith_type({bif, Op}, Args) of
+ any -> Res0;
+ Ret0 -> Res0;
+ Ret -> {meet(Ret, Ret0), ArgTypes, SubSafe}
+ end
end.
join_tuple_elements(Tuple) ->
diff --git a/lib/compiler/test/beam_bounds_SUITE.erl b/lib/compiler/test/beam_bounds_SUITE.erl
index 93021cad0e..e10f25c688 100644
--- a/lib/compiler/test/beam_bounds_SUITE.erl
+++ b/lib/compiler/test/beam_bounds_SUITE.erl
@@ -197,6 +197,8 @@ bnot_bounds(_Config) ->
{'-inf',-8} = beam_bounds:bounds('bnot', {7,'+inf'}),
{'-inf',9} = beam_bounds:bounds('bnot', {-10,'+inf'}),
+ -1 = bnot_bounds_2(0),
+
ok.
bnot_bounds_1(R) ->
@@ -211,6 +213,10 @@ bnot_bounds_1(R) ->
ct:fail(bad_min_or_max)
end.
+%% GH-7145: 'bnot' converged too slowly, effectively hanging the compiler.
+bnot_bounds_2(0) -> -1;
+bnot_bounds_2(N) -> abs(bnot bnot_bounds_2(N)).
+
bsr_bounds(_Config) ->
test_noncommutative('bsr', {-12,12}, {0,7}),
diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl
index 713a1ea5ab..65fecd5b7c 100644
--- a/lib/compiler/test/beam_jump_SUITE.erl
+++ b/lib/compiler/test/beam_jump_SUITE.erl
@@ -82,6 +82,8 @@ ambiguous_catch_try_state(Config) ->
{'EXIT',{{badmatch,0},_}} = (catch ambiguous_catch_try_state_2()),
{'EXIT',{{badmatch,0},_}} = (catch ambiguous_catch_try_state_3()),
+ {'EXIT',{badarg,_}} = catch ambiguous_catch_try_state_4(),
+
ok.
river() -> song.
@@ -229,6 +231,12 @@ ambiguous_catch_try_state_3() ->
end.
+ambiguous_catch_try_state_4() ->
+ 0.0 = try binary_to_float(garbage_collect() orelse ((1.0 = tuple_to_list(ok)) -- ok))
+ after
+ ok
+ end.
+
-record(message2, {id, p1}).
-record(message3, {id, p1, p2}).
diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl
index f6b0eb2929..0bb485c7f1 100644
--- a/lib/compiler/test/beam_ssa_SUITE.erl
+++ b/lib/compiler/test/beam_ssa_SUITE.erl
@@ -18,6 +18,7 @@
%% %CopyrightEnd%
%%
-module(beam_ssa_SUITE).
+-feature(maybe_expr, enable).
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
@@ -26,7 +27,7 @@
beam_ssa_dead_crash/1,stack_init/1,
mapfoldl/0,mapfoldl/1,
grab_bag/1,redundant_br/1,
- coverage/1]).
+ coverage/1,normalize/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -47,7 +48,8 @@ groups() ->
stack_init,
grab_bag,
redundant_br,
- coverage
+ coverage,
+ normalize
]}].
init_per_suite(Config) ->
@@ -904,6 +906,8 @@ grab_bag(_Config) ->
6 = grab_bag_21(id(64)),
{'EXIT',{badarith,_}} = catch grab_bag_21(id(a)),
+ false = grab_bag_22(),
+
ok.
grab_bag_1() ->
@@ -1180,6 +1184,18 @@ grab_bag_21(A) ->
grab_bag_21(_, D, _, _) ->
D.
+%% GH-7128: With optimizations disabled, the code would fail to
+%% load with the following message:
+%%
+%% beam/beam_load.c(367): Error loading function
+%% beam_ssa_no_opt_SUITE:grab_bag_22/0: op get_list: Sdd:
+%% bad tag 2 for destination
+grab_bag_22() ->
+ maybe
+ [_ | _] ?= ((true xor true) andalso foo),
+ bar ?= id(42)
+ end.
+
redundant_br(_Config) ->
{false,{x,y,z}} = redundant_br_1(id({x,y,z})),
{true,[[a,b,c]]} = redundant_br_1(id([[[a,b,c]]])),
@@ -1245,5 +1261,90 @@ coverage_5() ->
error
end#coverage{name = whatever}.
+%% Test beam_ssa:normalize/1, especially that argument types are
+%% correctly updated when arguments are swapped.
+normalize(_Config) ->
+ normalize_commutative({bif,'band'}),
+ normalize_commutative({bif,'+'}),
+
+ normalize_noncommutative({bif,'div'}),
+
+ ok.
+
+-record(b_var, {name}).
+-record(b_literal, {val}).
+
+normalize_commutative(Op) ->
+ A = #b_var{name=a},
+ B = #b_var{name=b},
+ Lit = #b_literal{val=42},
+
+ normalize_same(Op, [A,B]),
+ normalize_same(Op, [A,Lit]),
+
+ normalize_swapped(Op, [Lit,A]),
+
+ ok.
+
+normalize_noncommutative(Op) ->
+ A = #b_var{name=a},
+ B = #b_var{name=b},
+ Lit = #b_literal{val=42},
+
+ normalize_same(Op, [A,B]),
+ normalize_same(Op, [A,Lit]),
+
+ ArgTypes0 = [{1,beam_types:make_integer(0, 1023)}],
+ I1 = make_bset(ArgTypes0, Op, [Lit,A]),
+ I1 = beam_ssa:normalize(I1),
+
+ ok.
+
+normalize_same(Op, Args) ->
+ I0 = make_bset(#{}, Op, Args),
+ I0 = beam_ssa:normalize(I0),
+
+ ArgTypes0 = [{0,beam_types:make_integer(0, 1023)}],
+ I1 = make_bset(ArgTypes0, Op, Args),
+ I1 = beam_ssa:normalize(I1),
+
+ case Args of
+ [#b_var{},#b_var{}] ->
+ ArgTypes1 = [{0,beam_types:make_integer(0, 1023)},
+ {1,beam_types:make_integer(42)}],
+ I2 = make_bset(ArgTypes1, Op, Args),
+ I2 = beam_ssa:normalize(I2);
+ [_,_] ->
+ ok
+ end,
+
+ ok.
+
+normalize_swapped(Op, [#b_literal{}=Lit,#b_var{}=Var]=Args) ->
+ EmptyAnno = #{},
+ I0 = make_bset(EmptyAnno, Op, Args),
+ {b_set,EmptyAnno,#b_var{name=1000},Op,[Var,Lit]} = beam_ssa:normalize(I0),
+
+ EmptyTypes = #{arg_types => #{}},
+ I1 = make_bset(EmptyTypes, Op, Args),
+ {b_set,EmptyTypes,#b_var{name=1000},Op,[Var,Lit]} = beam_ssa:normalize(I1),
+
+ IntRange = beam_types:make_integer(0, 1023),
+ ArgTypes0 = [{1,IntRange}],
+ I2 = make_bset(ArgTypes0, Op, Args),
+ {[{0,IntRange}],Op,[Var,Lit]} = unpack_bset(beam_ssa:normalize(I2)),
+
+ ok.
+
+make_bset(ArgTypes, Op, Args) when is_list(ArgTypes) ->
+ Anno = #{arg_types => maps:from_list(ArgTypes)},
+ {b_set,Anno,#b_var{name=1000},Op,Args};
+make_bset(Anno, Op, Args) when is_map(Anno) ->
+ {b_set,Anno,#b_var{name=1000},Op,Args}.
+
+unpack_bset({b_set,Anno,{b_var,1000},Op,Args}) ->
+ ArgTypes = maps:get(arg_types, Anno, #{}),
+ {lists:sort(maps:to_list(ArgTypes)),Op,Args}.
+
%% The identity function.
id(I) -> I.
diff --git a/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl b/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl
index 4d4b0f1bbd..c1edc54460 100644
--- a/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl
+++ b/lib/compiler/test/beam_ssa_check_SUITE_data/private_append.erl
@@ -22,6 +22,8 @@
%%
-module(private_append).
+-feature(maybe_expr, enable).
+
-export([transformable0/1,
transformable1/1,
transformable1b/1,
@@ -76,7 +78,9 @@
not_transformable14/0,
not_transformable15/2,
- id/1]).
+ id/1,
+
+ bs_create_bin_on_literal/0]).
%% Trivial smoke test
transformable0(L) ->
@@ -977,3 +981,24 @@ not_transformable15(_, V) ->
id(I) ->
I.
+
+%% Check that we don't try to private_append to something created by
+%% bs_create_bin `append`, _, `<<>>`, ...
+bs_create_bin_on_literal() ->
+%ssa% () when post_ssa_opt ->
+%ssa% X = bs_init_writable(_),
+%ssa% Y = bs_create_bin(private_append, _, X, ...),
+%ssa% Z = bs_create_bin(private_append, _, Y, ...),
+%ssa% ret(Z).
+ <<
+ <<
+ (maybe
+ 2147483647 ?= ok
+ else
+ <<_>> ->
+ ok;
+ _ ->
+ <<>>
+ end)/bytes
+ >>/binary
+ >>.
diff --git a/lib/compiler/test/beam_ssa_check_SUITE_data/sanity_checks.erl b/lib/compiler/test/beam_ssa_check_SUITE_data/sanity_checks.erl
index ae4bb28eea..47c60fd8d6 100644
--- a/lib/compiler/test/beam_ssa_check_SUITE_data/sanity_checks.erl
+++ b/lib/compiler/test/beam_ssa_check_SUITE_data/sanity_checks.erl
@@ -18,6 +18,8 @@
-module(sanity_checks).
+-compile(no_ssa_opt_private_append).
+
-export([check_fail/0,
check_wrong_pass/0,
check_xfail/0,
@@ -33,7 +35,9 @@
t25/0, t26/0, t27/0, t28/0, t29/0,
t30/0, t31/0, t32/1, t33/1, t34/1,
t35/1, t36/0, t37/0, t38/0, t39/1,
- t40/0, t41/0, t42/0, t43/0, t44/0]).
+ t40/0, t41/0, t42/0, t43/0, t44/0,
+
+ check_env/0]).
%% Check that we do not trigger on the wrong pass
check_wrong_pass() ->
@@ -325,3 +329,13 @@ t44() ->
%ssa% () when post_ssa_opt ->
%ssa% _ = call(fun e:f0/1, {...}).
e:f0({}).
+
+%% Ensure bug which trashed the environment after matching a literal
+%% bitstring stays fixed.
+check_env() ->
+%ssa% () when post_ssa_opt ->
+%ssa% X = bs_create_bin(append, _, <<>>, ...),
+%ssa% ret(X).
+ A = <<>>,
+ B = ex:f(),
+ <<A/binary, B/binary>>.
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 0b00e6d71c..707c7ca80b 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -22,14 +22,16 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
integers/1,numbers/1,coverage/1,booleans/1,setelement/1,
- cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1,
+ cons/1,tuple/1,
+ record_float/1,binary_float/1,float_compare/1,float_overflow/1,
arity_checks/1,elixir_binaries/1,find_best/1,
test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1,
none_argument/1,success_type_oscillation/1,type_subtraction/1,
container_subtraction/1,is_list_opt/1,connected_tuple_elements/1,
switch_fail_inference/1,failures/1,
cover_maps_functions/1,min_max_mixed_types/1,
- not_equal/1,infer_relops/1,binary_unit/1,premature_concretization/1]).
+ not_equal/1,infer_relops/1,binary_unit/1,premature_concretization/1,
+ funs/1]).
%% Force id/1 to return 'any'.
-export([id/1]).
@@ -51,6 +53,7 @@ groups() ->
record_float,
binary_float,
float_compare,
+ float_overflow,
arity_checks,
elixir_binaries,
find_best,
@@ -71,7 +74,8 @@ groups() ->
not_equal,
infer_relops,
binary_unit,
- premature_concretization
+ premature_concretization,
+ funs
]}].
init_per_suite(Config) ->
@@ -741,11 +745,17 @@ record_float(R, N0) ->
binary_float(_Config) ->
<<-1/float>> = binary_negate_float(<<1/float>>),
+ {'EXIT',{badarg,_}} = catch binary_float_1(id(64.0), id(0)),
ok.
binary_negate_float(<<Float/float>>) ->
<<-Float/float>>.
+%% GH-7147.
+binary_float_1(X, Y) ->
+ _ = <<Y:(ceil(64.0 = X))/float, (binary_to_integer(ok))>>,
+ ceil(X) band Y.
+
float_compare(_Config) ->
false = do_float_compare(-42.0),
false = do_float_compare(-42),
@@ -765,6 +775,46 @@ do_float_compare(X) ->
_T -> Y > 0
end.
+float_overflow(_Config) ->
+ Res1 = id((1 bsl 1023) * two()),
+ Res1 = float_overflow_1(),
+
+ Res2 = id((-1 bsl 1023) * two()),
+ Res2 = float_overflow_2(),
+
+ {'EXIT',{{bad_filter,[0]},_}} = catch float_overflow_3(),
+
+ ok.
+
+%% GH-7178: There would be an overflow when converting a number range
+%% to a float range.
+float_overflow_1() ->
+ round(
+ try
+ round(float(1 bsl 1023)) * two()
+ catch
+ _:_ ->
+ 0.0
+ end
+ ).
+
+float_overflow_2() ->
+ round(
+ try
+ round(float(-1 bsl 1023)) * two()
+ catch
+ _:_ ->
+ 0.0
+ end
+ ).
+
+two() -> 2.
+
+float_overflow_3() ->
+ [0 || <<>> <= <<>>,
+ [0 || (floor(1.7976931348623157e308) bsl 1) >= (1.0 + map_size(#{}))]
+ ].
+
arity_checks(_Config) ->
%% ERL-549: an unsafe optimization removed a test_arity instruction,
%% causing the following to return 'broken' instead of 'ok'.
@@ -1363,5 +1413,30 @@ pm_concretization_2(_, Tagged) -> {error, Tagged}.
pm_concretization_3(_) -> ok.
pm_concretization_4(_) -> ok.
+funs(_Config) ->
+ {'EXIT',{badarg,_}} = catch gh_7179(),
+ false = is_function(id(fun() -> ok end), 1024),
+
+ {'EXIT',{badarg,_}} = catch gh_7197(),
+
+ ok.
+
+%% GH-7179: The beam_ssa_type pass would crash.
+gh_7179() ->
+ << <<0>> || is_function([0 || <<_>> <= <<>>], -1),
+ [] <- [] >>.
+
+%% GH-7197: The beam_ssa_type pass would crash.
+gh_7197() ->
+ [0 || is_function([ok || <<_>> <= <<>>], get_keys()),
+ fun (_) ->
+ ok
+ end].
+
+
+%%%
+%%% Common utilities.
+%%%
+
id(I) ->
I.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 6b63f561c1..2092d7401a 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -43,7 +43,7 @@
container_performance/1,
infer_relops/1,
not_equal_inference/1,bad_bin_unit/1,singleton_inference/1,
- inert_update_type/1]).
+ inert_update_type/1,range_inference/1]).
-include_lib("common_test/include/ct.hrl").
@@ -80,7 +80,7 @@ groups() ->
bs_saved_position_units,parent_container,
container_performance,infer_relops,
not_equal_inference,bad_bin_unit,singleton_inference,
- inert_update_type]}].
+ inert_update_type,range_inference]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -1129,5 +1129,22 @@ mike([Head | _Rest]) -> joe(Head).
joe({Name, 42}) -> Name;
joe({sys_period, {A, _B}}) -> {41, 42, A}.
+range_inference(_Config) ->
+ ok = range_inference_1(id(<<$a>>)),
+ ok = range_inference_1(id(<<0>>)),
+ ok = range_inference_1(id(<<1114111/utf8>>)),
+
+ ok.
+
+range_inference_1(<<X/utf8>>) ->
+ case 9223372036854775807 - abs(X) of
+ Y when X < Y ->
+ ok;
+ 9223372036854775807 ->
+ ok;
+ -2147483648 ->
+ ok
+ end.
+
id(I) ->
I.
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index 34bf54a871..e58db29114 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,8 @@
init_per_group/2,end_per_group/2,
beam_validator/1,trunc_and_friends/1,cover_safe_and_pure_bifs/1,
cover_trim/1,
- head_tail/1]).
+ head_tail/1,
+ min_max/1]).
suite() ->
[{ct_hooks,[ts_install_cth]}].
@@ -34,12 +35,13 @@ all() ->
[{group,p}].
groups() ->
- [{p,[parallel],
+ [{p,test_lib:parallel(),
[beam_validator,
trunc_and_friends,
cover_safe_and_pure_bifs,
cover_trim,
- head_tail
+ head_tail,
+ min_max
]}].
init_per_suite(Config) ->
@@ -192,5 +194,40 @@ tail_case() ->
X -> {X, ok}
end.
+min_max(_Config) ->
+ False = id(false),
+ True = id(true),
+
+ false = bool_min_false(False, False),
+ false = bool_min_false(False, True),
+ false = bool_min_false(True, False),
+ true = bool_min_true(True, True),
+
+ false = bool_max_false(False, False),
+ true = bool_max_true(False, True),
+ true = bool_max_true(True, False),
+ true = bool_max_true(True, True),
+
+ ok.
+
+%% GH-7170: The following functions would cause a crash in
+%% beam_ssa_codegen.
+
+bool_min_false(A, B) when is_boolean(A), is_boolean(B) ->
+ false = min(A, B).
+
+bool_min_true(A, B) when is_boolean(A), is_boolean(B) ->
+ true = min(A, B).
+
+bool_max_false(A, B) when is_boolean(A), is_boolean(B) ->
+ false = max(A, B).
+
+bool_max_true(A, B) when is_boolean(A), is_boolean(B) ->
+ true = max(A, B).
+
+%%%
+%%% Common utilities.
+%%%
+
id(I) ->
I.
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index 0d2c7f0654..bc6ed43dad 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -31,7 +31,7 @@
two/1,test1/1,fail/1,float_bin/1,in_guard/1,in_catch/1,
nasty_literals/1,coerce_to_float/1,side_effect/1,
opt/1,otp_7556/1,float_arith/1,otp_8054/1,
- strings/1,bad_size/1]).
+ strings/1,bad_size/1,private_append/1]).
-include_lib("common_test/include/ct.hrl").
@@ -47,7 +47,7 @@ groups() ->
[verify_highest_opcode,
two,test1,fail,float_bin,in_guard,in_catch,
nasty_literals,side_effect,opt,otp_7556,float_arith,
- otp_8054,strings,bad_size]}].
+ otp_8054,strings,bad_size,private_append]}].
init_per_suite(Config) ->
@@ -754,3 +754,26 @@ bad_binary_size2() ->
bad_binary_size3(Bin) ->
<<Bin:all/binary>>.
+
+private_append(_Config) ->
+ <<"alpha=\"alpha\",beta=\"beta\"">> =
+ private_append_1(#{ <<"alpha">> => <<"alpha">>,
+ <<"beta">> => <<"beta">> }),
+
+ <<>> = private_append_2(false),
+ {'EXIT', _} = catch private_append_2(true),
+
+ ok.
+
+%% GH-7121: Alias analysis would not mark fun arguments as aliased, fooling
+%% the beam_ssa_private_append pass.
+private_append_1(M) when is_map(M) ->
+ maps:fold(fun (K, V, Acc = <<>>) ->
+ <<Acc/binary, K/binary, "=\"", V/binary, "\"">>;
+ (K, V, Acc) ->
+ <<Acc/binary, ",", K/binary, "=\"", V/binary, "\"">>
+ end, <<>>, M).
+
+%% GH-7142: The private append pass crashed on oddly structured code.
+private_append_2(Boolean) ->
+ <<<<(id(Boolean) orelse <<>>)/binary>>/binary>>.
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index ed397a2e9f..b856f4044b 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -1577,7 +1577,7 @@ pre_load_check(Config) ->
try
do_pre_load_check(Config)
after
- dbg:stop_clear()
+ dbg:stop()
end
end.
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 0a39fcf419..fa46ea4097 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 8.2.4
+COMPILER_VSN = 8.2.6
diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c
index 4bcab0ec6e..15a08470a6 100644
--- a/lib/crypto/c_src/dh.c
+++ b/lib/crypto/c_src/dh.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
/* Has 3_0 */
ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (PrivKey|undefined, DHParams=[P,G], 0, Len|0) */
- unsigned long len = 0;
+ ErlNifUInt64 len = 0;
int i = 0;
OSSL_PARAM params[8];
EVP_PKEY *pkey = NULL, *pkey_gen = NULL;
@@ -84,7 +84,7 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
*/
/* argv[3] is the length of the private key that is to be generated */
- if (!enif_get_ulong(env, argv[3], &len) ||
+ if (!enif_get_uint64(env, argv[3], &len) ||
(len > LONG_MAX) ) {
ret = EXCP_BADARG_N(env, 3, "Bad value of length element");
goto done;
diff --git a/lib/crypto/c_src/openssl_config.h b/lib/crypto/c_src/openssl_config.h
index 9c7b05660e..e356cf94fb 100644
--- a/lib/crypto/c_src/openssl_config.h
+++ b/lib/crypto/c_src/openssl_config.h
@@ -127,6 +127,15 @@
# define HAS_EVP_PKEY_CTX
# define HAVE_EVP_CIPHER_CTX_COPY
# endif
+# if LIBRESSL_VERSION_NUMBER >= 0x3070200fL
+# define HAVE_PKEY_new_raw_private_key
+# endif
+# if LIBRESSL_VERSION_NUMBER >= 0x3030300fL
+# define HAVE_EVP_PKEY_new_CMAC_key
+# endif
+# if LIBRESSL_VERSION_NUMBER >= 0x3040100fL
+# define HAVE_DigestSign_as_single_op
+# endif
#endif
#if defined(HAS_EVP_PKEY_CTX) \
diff --git a/lib/crypto/doc/src/new_api.xml b/lib/crypto/doc/src/new_api.xml
index 87d77d0289..d4a71c9e61 100644
--- a/lib/crypto/doc/src/new_api.xml
+++ b/lib/crypto/doc/src/new_api.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2014</year><year>2021</year>
+ <year>2014</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 954d5cd664..fa5e9d5bea 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -31,6 +31,22 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 5.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, random errors are fixed for
+ crypto:generate_key calls with OpenSSL 3.</p>
+ <p>
+ Own Id: OTP-18555</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 5.1.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 69b01e6418..6abaacad5c 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -685,8 +685,6 @@ hash_final_xof(Context, Length) ->
-type hmac_hash_algorithm() :: sha1() | sha2() | sha3() | compatibility_only_hash().
-type cmac_cipher_algorithm() :: aes_128_cbc | aes_192_cbc | aes_256_cbc | aes_cbc
- | aes_128_cfb128 | aes_192_cfb128 | aes_256_cfb128 | aes_cfb128
- | aes_128_cfb8 | aes_192_cfb8 | aes_256_cfb8 | aes_cfb8
| blowfish_cbc
| des_cbc | des_ede3_cbc
| rc2_cbc
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 516ad02ee2..0572feaf33 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -1,7 +1,7 @@
%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -411,11 +411,11 @@ groups() ->
{ecdh, [], [compute, generate, use_all_ecdh_generate_compute]},
{eddh, [], [compute, generate, use_all_eddh_generate_compute]},
{srp, [], [generate_compute]},
- {des_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {des_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{des_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac]},
+ {des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{des_ede3_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {rc2_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {rc2_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{aes_cfb8, [], []},
{aes_128_cfb8, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_192_cfb8, [], [api_ng, api_ng_one_shot, api_ng_tls]},
@@ -426,7 +426,7 @@ groups() ->
{aes_192_cfb128, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_256_cfb128, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{no_aes_cfb128, [], [no_support]},
- {blowfish_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {blowfish_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{blowfish_ecb, [], [api_ng, api_ng_one_shot]},
{blowfish_cfb64, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{blowfish_ofb64, [], [api_ng, api_ng_one_shot, api_ng_tls]},
@@ -473,15 +473,15 @@ groups() ->
{des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{des_ede3_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_128_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
- {aes_192_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_256_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac]},
+ {aes_192_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
+ {aes_256_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{aes_128_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_192_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_256_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_128_ccm, [], [aead_ng, aead_bad_tag]},
{aes_192_ccm, [], [aead_ng, aead_bad_tag]},
{aes_256_ccm, [], [aead_ng, aead_bad_tag]},
- {aes_128_ecb, [], [api_ng, api_ng_one_shot, cmac_update]},
+ {aes_128_ecb, [], [api_ng, api_ng_one_shot]},
{aes_192_ecb, [], [api_ng, api_ng_one_shot]},
{aes_256_ecb, [], [api_ng, api_ng_one_shot]},
{aes_128_gcm, [], [aead_ng, aead_bad_tag]},
@@ -2378,6 +2378,8 @@ do_configure_mac(cmac, Cipher, Config) ->
case Cipher of
aes_128_cbc ->
fun() -> read_rsp(Config, Cipher, ["CMACGenAES128.rsp", "CMACVerAES128.rsp"]) end;
+ aes_192_cbc ->
+ fun() -> read_rsp(Config, Cipher, ["CMACGenAES192.rsp", "CMACVerAES192.rsp"]) end;
aes_256_cbc ->
fun() -> read_rsp(Config, Cipher, ["CMACGenAES256.rsp", "CMACVerAES256.rsp"]) end;
des_ede3_cbc ->
@@ -2933,10 +2935,9 @@ hmac_inc(_) ->
[<<"Sampl">>, <<"e #1">>].
-cmac_key(aes_128_cbc) ->
- hexstr2bin("8eeca0d146fd09ffbbe0d47edcddfcec");
-cmac_key(aes_128_ecb) ->
- hexstr2bin("8eeca0d146fd09ffbbe0d47edcddfcec").
+cmac_key(SubType) ->
+ rand:bytes(
+ maps:get(key_length, crypto:cipher_info(SubType))).
cmac_inc(_) ->
[<<"Sampl">>, <<"e #1">>].
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 41dfbaef97..56f5a0f48e 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 5.1.3
+CRYPTO_VSN = 5.1.4
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index 05abcc4daf..334cfcb8d7 100644
--- a/lib/dialyzer/doc/src/dialyzer.xml
+++ b/lib/dialyzer/doc/src/dialyzer.xml
@@ -507,6 +507,32 @@ dialyzer --plts plt_1 ... plt_n -- files_to_analyze</code>
<p>Currently the only option used is the
<seeerl marker="#error_location"><c>error_location</c></seeerl> option.
</p>
+
+ <p><em>Dialyzer configuration file:</em></p>
+
+ <p>Dialyzer's configuration file may also be used to augment the default
+ options and those given directly to the Dialyzer command. It is commonly
+ used to avoid repeating options which would otherwise need to be given
+ explicitly to Dialyzer on every invocation.
+ </p>
+
+ <p>The location of the configuration file can be set via the
+ <c>DIALYZER_CONFIG</c> environment variable, and defaults to
+ within the <c>user_config</c> from <seemfa marker="stdlib:filename#basedir/3">
+ <c>filename:basedir/3</c></seemfa>.
+ </p>
+
+ <p>An example configuration file's contents might be:</p>
+
+ <code type="none">
+ {incremental,
+ {default_apps,[stdlib,kernel,erts]},
+ {default_warning_apps,[stdlib]}
+ }.
+ {warnings, [no_improper_lists]}.
+ {add_pathsa,["/users/samwise/potatoes/ebin"]}.
+ {add_pathsz,["/users/smeagol/fish/ebin"]}.
+ </code>
</section>
<section>
@@ -593,6 +619,12 @@ dialyzer --plts plt_1 ... plt_n -- files_to_analyze</code>
<name name="file_location"></name>
</datatype>
<datatype>
+ <name name="filename_opt"></name>
+ </datatype>
+ <datatype>
+ <name name="format_option"></name>
+ </datatype>
+ <datatype>
<name name="warn_option"></name>
<desc>
<p>See section <seeerl
diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src
index 9693aa66cd..311c019a31 100644
--- a/lib/dialyzer/src/dialyzer.app.src
+++ b/lib/dialyzer/src/dialyzer.app.src
@@ -56,6 +56,6 @@
{registered, []},
{applications, [compiler, kernel, stdlib]},
{env, []},
- {runtime_dependencies, ["wx-2.0","syntax_tools-2.0","stdlib-4.0",
+ {runtime_dependencies, ["wx-2.0","syntax_tools-2.0","stdlib-@OTP-18558@",
"kernel-8.0","erts-12.0",
"compiler-8.0"]}]}.
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index a502f7107d..ecfc509e34 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -415,8 +415,8 @@ message_to_string({app_call, [M, F, Args, Culprit, ExpectedType, FoundType]},
[M, F, a(Args, I), c(Culprit, I),
t(ExpectedType, I), t(FoundType, I)]);
message_to_string({bin_construction, [Culprit, Size, Seg, Type]}, I, _E) ->
- io_lib:format("Binary construction will fail since the ~s field ~s in"
- " segment ~s has type ~s\n",
+ io_lib:format("Binary construction will fail since the ~ts field ~ts in"
+ " segment ~ts has type ~ts\n",
[Culprit, c(Size, I), c(Seg, I), t(Type, I)]);
message_to_string({call, [M, F, Args, ArgNs, FailReason,
SigArgs, SigRet, Contract]}, I, _E) ->
diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl
index f34acb3410..26a4b0b0a5 100644
--- a/lib/dialyzer/src/dialyzer.hrl
+++ b/lib/dialyzer/src/dialyzer.hrl
@@ -157,6 +157,11 @@
'incremental'}
| {'warnings', [warn_option()]}
| {'get_warnings', boolean()}
+ | {'use_spec', boolean()}
+ | {'filename_opt', filename_opt()}
+ | {'callgraph_file', file:filename()}
+ | {'mod_deps_file', file:filename()}
+ | {'warning_files_rec', [DirName :: file:filename()]}
| {'error_location', error_location()}.
-type dial_options() :: [dial_option()].
-type filename_opt() :: 'basename' | 'fullpath'.
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index 6d163c2cf9..b5cc6c7392 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -504,10 +504,11 @@ expand_files(Analysis = #analysis{files = Files, start_from = StartFrom}) ->
case expand_files(Files, Ext, []) of
[] ->
Msg = "No " ++ Ext ++ " files to analyze" ++
- case StartFrom of
- byte_code -> " (no --src specified?)";
- src_code -> ""
- end,
+ case StartFrom of
+ byte_code -> " (no --src specified?)";
+ src_code -> ""
+ end ++
+ "\nConsider setting some default apps in your dialyzer.config file",
exit({error, Msg});
NewFiles ->
Analysis#analysis{files = NewFiles}
diff --git a/lib/dialyzer/src/dialyzer_cl_parse.erl b/lib/dialyzer/src/dialyzer_cl_parse.erl
index bb792bb15a..2babea0073 100644
--- a/lib/dialyzer/src/dialyzer_cl_parse.erl
+++ b/lib/dialyzer/src/dialyzer_cl_parse.erl
@@ -1,5 +1,3 @@
-%% -*- erlang-indent-level: 2 -*-
-%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
@@ -14,8 +12,7 @@
-module(dialyzer_cl_parse).
--export([start/0, get_lib_dir/1]).
--export([collect_args/1]). % used also by typer
+-export([start/0]).
-include("dialyzer.hrl").
@@ -27,564 +24,298 @@
| {'gui', #options{}}
| {'error', string()}.
--type deep_string() :: string() | [deep_string()].
-
-%%-----------------------------------------------------------------------
-
-spec start() -> dial_cl_parse_ret().
-
start() ->
- init(),
- Args = init:get_plain_arguments(),
- try
- Ret = cl(Args),
- Ret
- catch
- throw:{dialyzer_cl_parse_error, Msg} -> {error, Msg};
- _:R:S ->
- Msg = io_lib:format("~tp\n~tp\n", [R, S]),
- {error, lists:flatten(Msg)}
- end.
-
-cl(["--add_to_plt"|T]) ->
- put(dialyzer_options_analysis_type, plt_add),
- cl(T);
-cl(["--apps"|T]) ->
- T1 = get_lib_dir(T),
- {Args, T2} = collect_args(T1),
- append_var(dialyzer_options_files_rec, Args),
- cl(T2);
-cl(["--warning_apps"|T]) ->
- T1 = get_lib_dir(T),
- {Args, T2} = collect_args(T1),
- append_var(dialyzer_options_warning_files_rec, Args),
- cl(T2);
-cl(["--build_plt"|T]) ->
- put(dialyzer_options_analysis_type, plt_build),
- cl(T);
-cl(["--check_plt"|T]) ->
- put(dialyzer_options_analysis_type, plt_check),
- cl(T);
-cl(["-n"|T]) ->
- cl(["--no_check_plt"|T]);
-cl(["--no_check_plt"|T]) ->
- put(dialyzer_options_check_plt, false),
- cl(T);
-cl(["-nn"|T]) ->
- %% Ignored since Erlang/OTP 24.0.
- cl(T);
-cl(["--no_native"|T]) ->
- %% Ignored since Erlang/OTP 24.0.
- cl(T);
-cl(["--no_native_cache"|T]) ->
- %% Ignored since Erlang/OTP 24.0.
- cl(T);
-cl(["--plt_info"|T]) ->
- put(dialyzer_options_analysis_type, plt_info),
- cl(T);
-cl(["--get_warnings"|T]) ->
- put(dialyzer_options_get_warnings, true),
- cl(T);
-cl(["-D"|_]) ->
- cl_error("No defines specified after -D");
-cl(["-D"++Define|T]) ->
- Def = re:split(Define, "=", [{return, list}, unicode]),
- append_defines(Def),
- cl(T);
-cl(["-h"|_]) ->
- help_message();
-cl(["--help"|_]) ->
- help_message();
-cl(["-I"]) ->
- cl_error("no include directory specified after -I");
-cl(["-I", Dir|T]) ->
- append_include(Dir),
- cl(T);
-cl(["-I"++Dir|T]) ->
- append_include(Dir),
- cl(T);
-cl(["--input_list_file"]) ->
- cl_error("No input list file specified");
-cl(["--input_list_file",File|L]) ->
- read_input_list_file(File),
- cl(L);
-cl(["-c"++_|T]) ->
- NewTail = command_line(T),
- cl(NewTail);
-cl(["-r"++_|T0]) ->
- {Args, T} = collect_args(T0),
- append_var(dialyzer_options_files_rec, Args),
- cl(T);
-cl(["--remove_from_plt"|T]) ->
- put(dialyzer_options_analysis_type, plt_remove),
- cl(T);
-cl(["--incremental"|T]) ->
- put(dialyzer_options_analysis_type, incremental),
- cl(T);
-cl(["--com"++_|T]) ->
- NewTail = command_line(T),
- cl(NewTail);
-cl(["--output"]) ->
- cl_error("No outfile specified");
-cl(["-o"]) ->
- cl_error("No outfile specified");
-cl(["--output",Output|T]) ->
- put(dialyzer_output, Output),
- cl(T);
-cl(["--metrics_file",MetricsFile|T]) ->
- put(dialyzer_metrics, MetricsFile),
- cl(T);
-cl(["--module_lookup_file",ModuleLookupFile|T]) ->
- put(dialyzer_module_lookup, ModuleLookupFile),
- cl(T);
-cl(["--output_plt"]) ->
- cl_error("No outfile specified for --output_plt");
-cl(["--output_plt",Output|T]) ->
- put(dialyzer_output_plt, Output),
- cl(T);
-cl(["-o", Output|T]) ->
- put(dialyzer_output, Output),
- cl(T);
-cl(["-o"++Output|T]) ->
- put(dialyzer_output, Output),
- cl(T);
-cl(["--raw"|T]) ->
- put(dialyzer_output_format, raw),
- cl(T);
-cl(["--fullpath"|T]) ->
- put(dialyzer_filename_opt, fullpath),
- cl(T);
-cl(["--no_indentation"|T]) ->
- put(dialyzer_indent_opt, false),
- cl(T);
-cl(["-pa", Path|T]) ->
- case code:add_patha(Path) of
- true -> cl(T);
- {error, _} -> cl_error("Bad directory for -pa: " ++ Path)
- end;
-cl(["--plt"]) ->
- error("No plt specified for --plt");
-cl(["--plt", PLT|T]) ->
- put(dialyzer_init_plts, [PLT]),
- cl(T);
-cl(["--plts"]) ->
- error("No plts specified for --plts");
-cl(["--plts"|T]) ->
- {PLTs, NewT} = get_plts(T, []),
- put(dialyzer_init_plts, PLTs),
- cl(NewT);
-cl(["-q"|T]) ->
- put(dialyzer_options_report_mode, quiet),
- cl(T);
-cl(["--quiet"|T]) ->
- put(dialyzer_options_report_mode, quiet),
- cl(T);
-cl(["--src"|T]) ->
- put(dialyzer_options_from, src_code),
- cl(T);
-cl(["--no_spec"|T]) ->
- put(dialyzer_options_use_contracts, false),
- cl(T);
-cl(["--statistics"|T]) ->
- put(dialyzer_timing, true),
- cl(T);
-cl(["--resources"|T]) ->
- put(dialyzer_options_report_mode, quiet),
- put(dialyzer_timing, debug),
- cl(T);
-cl(["-v"|_]) ->
- io:format("Dialyzer version "++?VSN++"\n"),
- erlang:halt(?RET_NOTHING_SUSPICIOUS);
-cl(["--version"|_]) ->
- io:format("Dialyzer version "++?VSN++"\n"),
- erlang:halt(?RET_NOTHING_SUSPICIOUS);
-cl(["--verbose"|T]) ->
- put(dialyzer_options_report_mode, verbose),
- cl(T);
-cl(["-W"|_]) ->
- cl_error("-W given without warning");
-cl(["-Whelp"|_]) ->
- help_warnings();
-cl(["-W"++Warn|T]) ->
- append_var(dialyzer_warnings, [list_to_atom(Warn)]),
- cl(T);
-cl(["--dump_callgraph"]) ->
- cl_error("No outfile specified for --dump_callgraph");
-cl(["--dump_callgraph", File|T]) ->
- put(dialyzer_callgraph_file, File),
- cl(T);
-cl(["--dump_full_dependencies_graph"]) ->
- cl_error("No outfile specified for --dump_full_dependencies_graph");
-cl(["--dump_full_dependencies_graph", File|T]) ->
- put(dialyzer_mod_deps_file, File),
- cl(T);
-cl(["--gui"|T]) ->
- put(dialyzer_options_mode, gui),
- cl(T);
-cl(["--error_location", LineOrColumn|T]) ->
- put(dialyzer_error_location_opt, list_to_atom(LineOrColumn)),
- cl(T);
-cl(["--solver", Solver|T]) -> % not documented
- append_var(dialyzer_solvers, [list_to_atom(Solver)]),
- cl(T);
-cl([H|_] = L) ->
- case filelib:is_file(H) orelse filelib:is_dir(H) of
- true ->
- NewTail = command_line(L),
- cl(NewTail);
- false ->
- cl_error("Unknown option: " ++ H)
- end;
-cl([]) ->
- {RetTag, Opts} =
- case get(dialyzer_options_analysis_type) =:= plt_info of
- true ->
- put(dialyzer_options_analysis_type, plt_check),
- {plt_info, cl_options()};
- false ->
- case get(dialyzer_options_mode) of
- gui -> {gui, common_options()};
- cl ->
- case get(dialyzer_options_analysis_type) =:= plt_check of
- true -> {check_init, cl_options()};
- false -> {cl, cl_options()}
- end
- end
- end,
- case dialyzer_options:build(Opts) of
- {error, Msg} -> cl_error(Msg);
- OptsRecord -> {RetTag, OptsRecord}
- end.
-
-%%-----------------------------------------------------------------------
-
-command_line(T0) ->
- {Args, T} = collect_args(T0),
- append_var(dialyzer_options_files, Args),
- %% if all files specified are ".erl" files, set the 'src' flag automatically
- case lists:all(fun(F) -> filename:extension(F) =:= ".erl" end, Args) of
- true -> put(dialyzer_options_from, src_code);
- false -> ok
- end,
- T.
-
-read_input_list_file(File) ->
- case file:read_file(File) of
- {ok,Bin} ->
- Files = binary:split(Bin, <<"\n">>, [trim_all,global]),
- NewFiles = [binary_to_list(string:trim(F)) || F <- Files],
- append_var(dialyzer_options_files, NewFiles);
- {error,Reason} ->
- cl_error(io_lib:format("Reading of ~s failed: ~s", [File,file:format_error(Reason)]))
- end.
-
--spec cl_error(deep_string()) -> no_return().
-
-cl_error(Str) ->
- Msg = lists:flatten(Str),
- throw({dialyzer_cl_parse_error, Msg}).
-
-init() ->
- %% By not initializing every option, the modified options can be
- %% found. If every option were to be returned by cl_options() and
- %% common_options(), then the environment variables (currently only
- %% ERL_COMPILER_OPTIONS) would be overwritten by default values.
- put(dialyzer_options_mode, cl),
- put(dialyzer_options_files_rec, []),
- put(dialyzer_options_warning_files_rec, []),
- put(dialyzer_options_report_mode, normal),
- put(dialyzer_warnings, []),
- ok.
-
-append_defines([Def, Val]) ->
- {ok, Tokens, _} = erl_scan:string(Val++"."),
- {ok, ErlVal} = erl_parse:parse_term(Tokens),
- append_var(dialyzer_options_defines, [{list_to_atom(Def), ErlVal}]);
-append_defines([Def]) ->
- append_var(dialyzer_options_defines, [{list_to_atom(Def), true}]).
-
-append_include(Dir) ->
- append_var(dialyzer_include, [Dir]).
-
-append_var(Var, List) when is_list(List) ->
- case get(Var) of
- undefined ->
- put(Var, List);
- L ->
- put(Var, L ++ List)
- end,
- ok.
-
-%%-----------------------------------------------------------------------
-
--spec collect_args([string()]) -> {[string()], [string()]}.
-
-collect_args(List) ->
- collect_args_1(List, []).
-
-collect_args_1(["-"++_|_] = L, Acc) ->
- {lists:reverse(Acc), L};
-collect_args_1([Arg|T], Acc) ->
- collect_args_1(T, [Arg|Acc]);
-collect_args_1([], Acc) ->
- {lists:reverse(Acc), []}.
+ Args = init:get_plain_arguments(),
+ try argparse:parse(Args, cli(), #{progname => dialyzer}) of
+ {ok, ArgMap, _, _} ->
+ {Command, Opts} = postprocess_side_effects(ArgMap),
+ case dialyzer_options:build(maps:to_list(Opts)) of
+ {error, Msg2} ->
+ {error, Msg2};
+ OptsRecord ->
+ {Command, OptsRecord}
+ end;
+ {error, Error} ->
+ {error, argparse:format_error(Error)}
+ catch
+ throw:{dialyzer_cl_parse_error, Msg} ->
+ {error, Msg};
+ _:R:S ->
+ Msg = io_lib:format("~tp\n~tp\n", [R, S]),
+ {error, lists:flatten(Msg)}
+ end.
%%-----------------------------------------------------------------------
-cl_options() ->
- OptsList = [{files, dialyzer_options_files},
- {files_rec, dialyzer_options_files_rec},
- {warning_files_rec, dialyzer_options_warning_files_rec},
- {output_file, dialyzer_output},
- {metrics_file, dialyzer_metrics},
- {module_lookup_file, dialyzer_module_lookup},
- {output_format, dialyzer_output_format},
- {filename_opt, dialyzer_filename_opt},
- {indent_opt, dialyzer_indent_opt},
- {analysis_type, dialyzer_options_analysis_type},
- {get_warnings, dialyzer_options_get_warnings},
- {timing, dialyzer_timing},
- {callgraph_file, dialyzer_callgraph_file},
- {mod_deps_file, dialyzer_mod_deps_file}],
- get_options(OptsList) ++ common_options().
-
-common_options() ->
- OptsList = [{defines, dialyzer_options_defines},
- {from, dialyzer_options_from},
- {include_dirs, dialyzer_include},
- {plts, dialyzer_init_plts},
- {output_plt, dialyzer_output_plt},
- {report_mode, dialyzer_options_report_mode},
- {use_spec, dialyzer_options_use_contracts},
- {warnings, dialyzer_warnings},
- {check_plt, dialyzer_options_check_plt},
- {solvers, dialyzer_solvers}],
- get_options(OptsList).
-
-get_options(TagOptionList) ->
- lists:append([get_opt(Tag, Opt) || {Tag, Opt} <- TagOptionList]).
-
-get_opt(Tag, Opt) ->
- case get(Opt) of
- undefined ->
- [];
- V ->
- [{Tag, V}]
- end.
-
-%%-----------------------------------------------------------------------
-
--spec get_lib_dir([string()]) -> [string()].
-
-get_lib_dir(Apps) ->
- get_lib_dir(Apps, []).
-
-get_lib_dir([H|T], Acc) ->
- NewElem =
- case code:lib_dir(list_to_atom(H)) of
- {error, bad_name} -> H;
- LibDir when H =:= "erts" -> % hack for including erts in an un-installed system
- EbinDir = filename:join([LibDir,"ebin"]),
- case file:read_file_info(EbinDir) of
- {error,enoent} ->
- filename:join([LibDir,"preloaded","ebin"]);
- _ ->
- EbinDir
- end;
- LibDir -> filename:join(LibDir,"ebin")
- end,
- get_lib_dir(T, [NewElem|Acc]);
-get_lib_dir([], Acc) ->
- lists:reverse(Acc).
-
-%%-----------------------------------------------------------------------
-
-get_plts(["--"|T], Acc) -> {lists:reverse(Acc), T};
-get_plts(["-"++_Opt = H|T], Acc) -> {lists:reverse(Acc), [H|T]};
-get_plts([H|T], Acc) -> get_plts(T, [H|Acc]);
-get_plts([], Acc) -> {lists:reverse(Acc), []}.
-
-%%-----------------------------------------------------------------------
-
--spec help_warnings() -> no_return().
-
-help_warnings() ->
- S = warning_options_msg(),
- io:put_chars(S),
- erlang:halt(?RET_NOTHING_SUSPICIOUS).
-
--spec help_message() -> no_return().
-
-help_message() ->
- S = "Usage: dialyzer [--add_to_plt] [--apps applications] [--build_plt]
- [--check_plt] [-Ddefine]* [-Dname]* [--dump_callgraph file]
- [--error_location flag] [files_or_dirs] [--fullpath]
- [--get_warnings] [--gui] [--help] [-I include_dir]*
- [--incremental] [--metrics_file] [--no_check_plt] [--no_indentation] [--no_spec]
- [-o outfile] [--output_plt file] [-pa dir]* [--plt plt] [--plt_info]
- [--plts plt*] [--quiet] [-r dirs] [--raw] [--remove_from_plt]
- [--shell] [--src] [--statistics] [--verbose] [--version]
- [--warning_apps] [-Wwarn]*
-
-Options:
- files_or_dirs (for backwards compatibility also as: -c files_or_dirs)
- Use Dialyzer from the command line to detect defects in the
- specified files or directories containing .erl or .beam files,
- depending on the type of the analysis.
- -r dirs
- Same as the previous but the specified directories are searched
- recursively for subdirectories containing .erl or .beam files in
- them, depending on the type of analysis.
- --input_list_file file
- Specify the name of a file that contains the names of the files
- to be analyzed (one file name per line).
- --apps applications
- Option typically used when building or modifying a plt as in:
- dialyzer --build_plt --apps erts kernel stdlib mnesia ...
- to conveniently refer to library applications corresponding to the
- Erlang/OTP installation. However, the option is general and can also
- be used during analysis in order to refer to Erlang/OTP applications.
- In addition, file or directory names can also be included, as in:
- dialyzer --apps inets ssl ./ebin ../other_lib/ebin/my_module.beam
- --warning_apps applications
- By default, warnings will be reported to all applications given by
- --apps. However, if --warning_apps is used, only those applications
- given to --warning_apps will have warnings reported. All applications
- given by --apps, but not --warning_apps, will be analysed to provide
- context to the analysis, but warnings will not be reported for them.
- For example, you may want to include libraries you depend on in the
- analysis with --apps so discrepancies in their usage can be found,
- but only include your own code with --warning_apps so that
- discrepancies are only reported in code that you own.
- -o outfile (or --output outfile)
- When using Dialyzer from the command line, send the analysis
- results to the specified outfile rather than to stdout.
- --raw
- When using Dialyzer from the command line, output the raw analysis
- results (Erlang terms) instead of the formatted result.
- The raw format is easier to post-process (for instance, to filter
- warnings or to output HTML pages).
- --src
- Override the default, which is to analyze BEAM files, and
- analyze starting from Erlang source code instead.
- -Dname (or -Dname=value)
- When analyzing from source, pass the define to Dialyzer. (**)
- -I include_dir
- When analyzing from source, pass the include_dir to Dialyzer. (**)
- -pa dir
- Include dir in the path for Erlang (useful when analyzing files
- that have '-include_lib()' directives).
- --output_plt file
- Store the plt at the specified file after building it.
- --plt plt
- Use the specified plt as the initial plt (if the plt was built
- during setup the files will be checked for consistency).
- --plts plt*
- Merge the specified plts to create the initial plt -- requires
- that the plts are disjoint (i.e., do not have any module
- appearing in more than one plt).
- The plts are created in the usual way:
- dialyzer --build_plt --output_plt plt_1 files_to_include
- ...
- dialyzer --build_plt --output_plt plt_n files_to_include
- and then can be used in either of the following ways:
- dialyzer files_to_analyze --plts plt_1 ... plt_n
- or:
- dialyzer --plts plt_1 ... plt_n -- files_to_analyze
- (Note the -- delimiter in the second case)
- -Wwarn
- A family of options which selectively turn on/off warnings
- (for help on the names of warnings use dialyzer -Whelp).
- --shell
- Do not disable the Erlang shell while running the GUI.
- --version (or -v)
- Print the Dialyzer version and some more information and exit.
- --help (or -h)
- Print this message and exit.
- --quiet (or -q)
- Make Dialyzer a bit more quiet.
- --verbose
- Make Dialyzer a bit more verbose.
- --statistics
- Prints information about the progress of execution (analysis phases,
- time spent in each and size of the relative input).
- --build_plt
- The analysis starts from an empty plt and creates a new one from the
- files specified with -c and -r. Only works for beam files.
- Use --plt(s) or --output_plt to override the default plt location.
- --add_to_plt
- The plt is extended to also include the files specified with -c and -r.
- Use --plt(s) to specify which plt to start from, and --output_plt to
- specify where to put the plt. Note that the analysis might include
- files from the plt if they depend on the new files.
- This option only works with beam files.
- --remove_from_plt
- The information from the files specified with -c and -r is removed
- from the plt. Note that this may cause a re-analysis of the remaining
- dependent files.
- --check_plt
- Check the plt for consistency and rebuild it if it is not up-to-date.
- Actually, this option is of rare use as it is on by default.
- --no_check_plt (or -n)
- Skip the plt check when running Dialyzer. Useful when working with
- installed plts that never change.
- --incremental
- The analysis starts from an existing incremental PLT, or builds one from
- scratch if one doesn't exist, and runs the minimal amount of additional
- analysis to report all issues in the given set of apps. Notably, incremental
- PLT files are not compatible with \"classic\" PLT files, and vice versa.
- The initial incremental PLT will be updated unless an alternative output
- incremental PLT is given.
- --plt_info
- Make Dialyzer print information about the plt and then quit. The plt
- can be specified with --plt(s).
- --get_warnings
- Make Dialyzer emit warnings even when manipulating the plt. Warnings
- are only emitted for files that are actually analyzed.
- --dump_callgraph file
- Dump the call graph into the specified file whose format is determined
- by the file name extension. Supported extensions are: raw, dot, and ps.
- If something else is used as file name extension, default format '.raw'
- will be used.
- --dump_full_dependencies_graph file
- Dump the full dependency graph (i.e. dependencies induced by function
- calls, usages of types in specs, behaviour implementations, etc.) into
- the specified file whose format is determined by the file name
- extension. Supported extensions are: dot and ps.
- --metrics_file file
- Write metrics about Dialyzer's incrementality (for example, total number of
- modules considered, how many modules were changed since the PLT was
- last updated, how many modules needed to be analyzed) to a file. This
- can be useful for tracking and debugging Dialyzer's incrementality.
- --error_location column | line
- Use a pair {Line, Column} or an integer Line to pinpoint the location
- of warnings. The default is to use a pair {Line, Column}. When
- formatted, the line and the column are separated by a colon.
- --fullpath
- Display the full path names of files for which warnings are emitted.
- --no_indentation
- Do not indent contracts and success typings. Note that this option has
- no effect when combined with the --raw option.
- --no_spec
- Ignore functions specs. This is useful for debugging when one suspects
- that some specs are incorrect.
- --gui
- Use the GUI.
-
+parse_app(AppOrDir) ->
+ case code:lib_dir(list_to_atom(AppOrDir)) of
+ {error, bad_name} -> AppOrDir;
+ LibDir when AppOrDir =:= "erts" -> % hack for including erts in an un-installed system
+ EbinDir = filename:join([LibDir, "ebin"]),
+ case file:read_file_info(EbinDir) of
+ {error, enoent} ->
+ filename:join([LibDir, "preloaded", "ebin"]);
+ _ ->
+ EbinDir
+ end;
+ LibDir -> filename:join(LibDir, "ebin")
+ end.
+
+parse_input_list(File) ->
+ case file:read_file(File) of
+ {ok, Bin} ->
+ Files = binary:split(Bin, <<"\n">>, [trim_all, global]),
+ [binary_to_list(string:trim(F)) || F <- Files];
+ {error, Reason} ->
+ cl_error(io_lib:format("Reading of ~s failed: ~s", [File, file:format_error(Reason)]))
+ end.
+
+parse_define(Arg) ->
+ case re:split(Arg, "=", [{return, list}, unicode]) of
+ [Def, Val] ->
+ {ok, Tokens, _} = erl_scan:string(Val++"."),
+ {ok, ErlVal} = erl_parse:parse_term(Tokens),
+ {list_to_atom(Def), ErlVal};
+ [Def] ->
+ {list_to_atom(Def), true}
+ end.
+
+cli() ->
+ #{
+ arguments => [
+ #{name => files, action => extend, nargs => list, required => false,
+ help => <<"Use Dialyzer from the command line to detect defects in the "
+ "specified files or directories containing .erl or .beam files, "
+ "depending on the type of the analysis.">>},
+ #{name => files, short => $c, long => "-com", action => extend, nargs => list,
+ help => <<"Same as files, specifies files to run the analysis on (left for compatibility)">>},
+ #{name => files_rec, short => $r, action => extend, nargs => list,
+ help => <<"Search the specified directories "
+ "recursively for subdirectories containing .erl or .beam files in "
+ "them, depending on the type of analysis.">>},
+ #{name => files, long => "-input_list_file", type => {custom, fun parse_input_list/1},
+ action => extend,
+ help => <<"Specify the name of a file that contains the names of the files "
+ "to be analyzed (one file name per line).">>},
+ #{name => files_rec, long => "-apps", type => {custom, fun parse_app/1},
+ nargs => list, action => extend,
+ help => <<"Option typically used when building or modifying a plt as in: \n"
+ "dialyzer --build_plt --apps erts kernel stdlib mnesia ... \n"
+ "to conveniently refer to library applications corresponding to the "
+ "Erlang/OTP installation. However, the option is general and can also "
+ "be used during analysis in order to refer to Erlang/OTP applications. "
+ "In addition, file or directory names can also be included, as in: \n"
+ "dialyzer --apps inets ssl ./ebin ../other_lib/ebin/my_module.beam">>},
+
+ #{name => output_file, short => $o, long => "--output",
+ help => <<"When using Dialyzer from the command line, send the analysis "
+ "results to the specified outfile rather than to stdout.">>},
+ #{name => output_format, long => "-raw", type => boolean, action => {store, raw},
+ help => <<"When using Dialyzer from the command line, output the raw analysis "
+ "results (Erlang terms) instead of the formatted result. "
+ "The raw format is easier to post-process (for instance, to filter "
+ "warnings or to output HTML pages).">>},
+ #{name => from, long => "-src", type => boolean, action => {store, src_code},
+ help => <<"Override the default, which is to analyze BEAM files, and "
+ "analyze starting from Erlang source code instead.">>},
+ #{name => defines, short=>$D, type => {custom, fun parse_define/1}, action => append,
+ help => <<"When analyzing from source, pass the define to Dialyzer. (**)">>},
+ #{name => include_dirs, short=>$I, action => append,
+ help => <<"When analyzing from source, pass the include_dir to Dialyzer. (**)">>},
+ #{name => pa, long => "pa", action => append,
+ help => <<"Include dir in the path for Erlang (useful when analyzing files "
+ "that have '-include_lib()' directives).">>},
+ #{name => output_plt, long => "-output_plt",
+ help => <<"Store the plt at the specified file after building it.">>},
+ #{name => plts, long => "-plt", nargs => 1,
+ help => <<"Use the specified plt as the initial plt (if the plt was built "
+ "during setup the files will be checked for consistency).">>},
+ #{name => plts, long => "-plts", nargs => nonempty_list,
+ help => <<"Merge the specified plts to create the initial plt -- requires "
+ "that the plts are disjoint (i.e., do not have any module "
+ "appearing in more than one plt). "
+ "The plts are created in the usual way: \n"
+ " dialyzer --build_plt --output_plt plt_1 files_to_include "
+ " ... \n"
+ " dialyzer --build_plt --output_plt plt_n files_to_include "
+ "and then can be used in either of the following ways: \n"
+ " dialyzer files_to_analyze --plts plt_1 ... plt_n \n"
+ "or: \n"
+ " dialyzer --plts plt_1 ... plt_n -- files_to_analyze \n"
+ "(Note the -- delimiter in the second case)">>},
+ #{name => warnings, short => $W, action => append, type => {atom, [error_handling,
+ no_behaviours, no_contracts, no_fail_call, no_fun_app, no_improper_lists,
+ no_match, no_missing_calls, no_opaque, no_return, no_undefined_callbacks,
+ no_underspecs, no_unknown, no_unused, underspecs, unknown, unmatched_returns,
+ overspecs, specdiffs, extra_return, no_extra_return, missing_return, no_missing_return]},
+ help => {<<"[-Wwarn]*">>, [<<"A family of options which selectively turn on/off warnings">>]}},
+ #{name => shell, long => "-shell", type => boolean,
+ help => <<"Do not disable the Erlang shell while running the GUI.">>},
+ #{name => version, short => $v, long => "-version", type => boolean,
+ help => <<"Print the Dialyzer version and some more information and exit.">>},
+ #{name => help, short => $h, long => "-help", type => boolean,
+ help => <<"Print this message and exit.">>},
+ #{name => report_mode, short => $q, long => "-quiet", type => boolean, action => {store, quiet},
+ default => normal, help => <<"Make Dialyzer a bit more quiet.">>},
+ #{name => report_mode, long => "-verbose", type => boolean, action => {store, verbose},
+ help => <<"Make Dialyzer a bit more verbose.">>},
+ #{name => timing, long => "-statistics", type => boolean,
+ help => <<"Prints information about the progress of execution (analysis phases, "
+ "time spent in each and size of the relative input).">>},
+ #{name => analysis_type, long => "-build_plt", type => boolean, action => {store, plt_build},
+ help => <<"The analysis starts from an empty plt and creates a new one from the "
+ "files specified with -c and -r. Only works for beam files. "
+ "Use --plt(s) or --output_plt to override the default plt location.">>},
+ #{name => analysis_type, long=> "-add_to_plt", type => boolean, action => {store, plt_add},
+ help => <<"The plt is extended to also include the files specified with -c and -r. "
+ "Use --plt(s) to specify which plt to start from, and --output_plt to "
+ "specify where to put the plt. Note that the analysis might include "
+ "files from the plt if they depend on the new files. "
+ "This option only works with beam files.">>},
+ #{name => analysis_type, long => "-remove_from_plt", type => boolean, action => {store, plt_remove},
+ help => <<"The information from the files specified with -c and -r is removed "
+ "from the plt. Note that this may cause a re-analysis of the remaining "
+ "dependent files.">>},
+ #{name => analysis_type, long => "-check_plt", type => boolean, action => {store, plt_check},
+ help => <<"Check the plt for consistency and rebuild it if it is not up-to-date. "
+ "Actually, this option is of rare use as it is on by default.">>},
+ #{name => check_plt, long => "-no_check_plt", short => $n, type => boolean, action => {store, false},
+ help => <<"Skip the plt check when running Dialyzer. Useful when working with "
+ "installed plts that never change.">>},
+ #{name => analysis_type, long => "-incremental", type => boolean, action => {store, incremental},
+ help => <<"The analysis starts from an existing incremental PLT, or builds one from "
+ "scratch if one doesn't exist, and runs the minimal amount of additional "
+ "analysis to report all issues in the given set of apps. Notably, incremental "
+ "PLT files are not compatible with \"classic\" PLT files, and vice versa. "
+ "The initial incremental PLT will be updated unless an alternative output "
+ "incremental PLT is given.">>},
+ #{name => analysis_type, long => "-plt_info", type => boolean, action => {store, plt_info},
+ help => <<"Make Dialyzer print information about the plt and then quit. The plt "
+ "can be specified with --plt(s).">>},
+ #{name => get_warnings, long => "-get_warnings", type => boolean,
+ help => <<"Make Dialyzer emit warnings even when manipulating the plt. Warnings "
+ "are only emitted for files that are actually analyzed.">>},
+ #{name => callgraph_file, long => "-dump_callgraph",
+ help => <<"Dump the call graph into the specified file whose format is determined "
+ "by the file name extension. Supported extensions are: raw, dot, and ps. "
+ "If something else is used as file name extension, default format '.raw' "
+ "will be used.">>},
+ #{name => mod_deps_file, long => "-dump_full_dependencies_graph",
+ help => <<"Dump the full dependency graph (i.e. dependencies induced by function "
+ "calls, usages of types in specs, behaviour implementations, etc.) into "
+ "the specified file whose format is determined by the file name "
+ "extension. Supported extensions are: dot and ps.">>},
+ #{name => error_location, long => "-error_location", type => {atom, [column, line]},
+ help => <<"Use a pair {Line, Column} or an integer Line to pinpoint the location "
+ "of warnings. The default is to use a pair {Line, Column}. When "
+ "formatted, the line and the column are separated by a colon.">>},
+ #{name => filename_opt, long => "-fullpath", type => boolean, action => {store, fullpath},
+ help => <<"Display the full path names of files for which warnings are emitted.">>},
+ #{name => indent_opt, long => "-no_indentation", type => boolean, action => {store, false},
+ help => <<"Do not indent contracts and success typings. Note that this option has "
+ "no effect when combined with the --raw option.">>},
+ #{name => gui, long => "-gui", type => boolean,
+ help => <<"Use the GUI.">>},
+ #{name => metrics_file, long => "-metrics_file",
+ help => <<"Write metrics about Dialyzer's incrementality (for example, total number of "
+ "modules considered, how many modules were changed since the PLT was "
+ "last updated, how many modules needed to be analyzed) to a file. This "
+ "can be useful for tracking and debugging Dialyzer's incrementality.">>},
+ #{name => warning_files_rec, long => "-warning_apps", type => {custom, fun parse_app/1},
+ nargs => list, action => extend,
+ help => <<"By default, warnings will be reported to all applications given by "
+ "--apps. However, if --warning_apps is used, only those applications "
+ "given to --warning_apps will have warnings reported. All applications "
+ "given by --apps, but not --warning_apps, will be analysed to provide "
+ "context to the analysis, but warnings will not be reported for them. "
+ "For example, you may want to include libraries you depend on in the "
+ "analysis with --apps so discrepancies in their usage can be found, "
+ "but only include your own code with --warning_apps so that "
+ "discrepancies are only reported in code that you own.">>},
+
+ %% Intentionally undocumented options
+ #{name => solvers, long => "-solver", type => {atom, [v1, v2]}, action => append,
+ help => hidden},
+ #{name => timing, long => "-resources", type => boolean, action => {store, debug},
+ help => hidden},
+
+ %% next definition is necessary to ignore '--' left for compatibility reasons
+ #{name => shell, short => $-, type => boolean, help => hidden}
+ ],
+
+ help => [<<"Usage: ">>, usage, <<"\n\nOptions:\n">>,
+ arguments, options, "
Note:
* denotes that multiple occurrences of these options are possible.
** options -D and -I work both from command-line and in the Dialyzer GUI;
the syntax of defines and includes is the same as that used by \"erlc\".
" ++ warning_options_msg() ++ "
+" ++ configuration_file_msg() ++ "
+
The exit status of the command line version is:
0 - No problems were encountered during the analysis and no
warnings were emitted.
1 - Problems were encountered during the analysis.
2 - No problems were encountered, but warnings were emitted.
-",
- io:put_chars(S),
- erlang:halt(?RET_NOTHING_SUSPICIOUS).
+
+"]
+ }.
+
+postprocess_side_effects(ArgMap) when is_map_key(version, ArgMap) ->
+ %% Version handling
+ io:format("Dialyzer version " ++ ?VSN ++ "\n"),
+ erlang:halt(?RET_NOTHING_SUSPICIOUS);
+
+postprocess_side_effects(ArgMap) when is_map_key(help, ArgMap) ->
+ %% Help message
+ io:format(argparse:help(cli(), #{progname => dialyzer})),
+ erlang:halt(?RET_NOTHING_SUSPICIOUS);
+
+postprocess_side_effects(ArgMap) when is_map_key(pa, ArgMap) ->
+ %% Code path side effect
+ [code:add_patha(Path) =/= true andalso cl_error("Bad directory for -pa: " ++ Path) ||
+ Path <- map_get(pa, ArgMap)],
+ postprocess_side_effects(maps:remove(pa, ArgMap));
+
+postprocess_side_effects(ArgMap) when is_map_key(shell, ArgMap) ->
+ %% --shell option is processed by C executable (left here only for help/usage)
+ postprocess_side_effects(maps:remove(shell, ArgMap));
+
+postprocess_side_effects(ArgMap) ->
+ %% if all files specified are ".erl" files, set the 'src' flag automatically
+ %% it is compatibility behaviour, potentially incorrect, because it does not take
+ %% directories (rec_files) into account
+ ArgMap1 =
+ case (is_map_key(files, ArgMap) andalso
+ lists:all(fun(F) -> filename:extension(F) =:= ".erl" end, maps:get(files, ArgMap))) of
+ true ->
+ ArgMap#{from => src_code};
+ false ->
+ ArgMap
+ end,
+
+ %% Run mode (command) is defined by the flag combination
+ case maps:get(analysis_type, ArgMap1, undefined) of
+ plt_info ->
+ %% plt_info is plt_check analysis type
+ {plt_info, ArgMap1#{analysis_type => plt_check}};
+ plt_check ->
+ %% plt_check is a hidden "check_init" command
+ {check_init, ArgMap1};
+ _ when map_get(gui, ArgMap1) ->
+ %% filter out command-line only arguments
+ Allowed = [defines, from, include_dirs, plts, output_plt, report_mode,
+ use_spec, warnings, check_plt, solvers],
+ {gui, maps:with(Allowed, ArgMap1)};
+ _ ->
+ {cl, ArgMap1}
+ end.
+
+cl_error(Str) ->
+ Msg = lists:flatten(Str),
+ throw({dialyzer_cl_parse_error, Msg}).
warning_options_msg() ->
"Warning options:
@@ -654,3 +385,29 @@ They are primarily intended to be used with the -dialyzer attribute:
-Wno_missing_return
Suppress warnings about functions that return values that are not part of the specification.
".
+
+configuration_file_msg() ->
+ "Configuration file:
+ Dialyzer's configuration file may also be used to augment the default
+ options and those given directly to the Dialyzer command. It is commonly
+ used to avoid repeating options which would otherwise need to be given
+ explicitly to Dialyzer on every invocation.
+
+ The location of the configuration file can be set via the
+ DIALYZER_CONFIG environment variable, and defaults to
+ within the user_config location given by filename:basedir/3.
+
+ On your system, the location is currently configured as:
+ " ++ dialyzer_options:get_default_config_filename() ++
+ "
+
+ An example configuration file's contents might be:
+
+ {incremental,
+ {default_apps,[stdlib,kernel,erts]},
+ {default_warning_apps,[stdlib]}
+ }.
+ {warnings, [no_improper_lists]}.
+ {add_pathsa,[\"/users/samwise/potatoes/ebin\"]}.
+ {add_pathsz,[\"/users/smeagol/fish/ebin\"]}.
+".
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index bb77ea972f..7e0a75f062 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -1602,20 +1602,23 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) ->
UnitVal = cerl:concrete(cerl:bitstr_unit(Seg)),
Size = cerl:bitstr_size(Seg),
case bitstr_bitsize_type(Size) of
- all ->
- binary = SegType, [] = Segs, %% just an assert
+ {literal, all} ->
+ binary = SegType, [] = Segs, %Assertion.
T = t_inf(t_bitstr(UnitVal, 0), BinType),
{Map1, [Type]} = do_bind_pat_vars([Val], [T], Map,
State, false, []),
Type1 = remove_local_opaque_types(Type, State#state.opaques),
bind_bin_segs(Segs, t_bitstr(0, 0), [Type1|Acc], Map1, State);
- utf -> % XXX: can possibly be strengthened
- true = lists:member(SegType, [utf8, utf16, utf32]),
+ SizeType when SegType =:= utf8; SegType =:= utf16; SegType =:= utf32 ->
+ {literal, undefined} = SizeType, %Assertion.
{Map1, [_]} = do_bind_pat_vars([Val], [t_integer()],
Map, State, false, []),
Type = t_binary(),
bind_bin_segs(Segs, BinType, [Type|Acc], Map1, State);
- any ->
+ {literal, N} when not is_integer(N); N < 0 ->
+ %% Bogus literal size, fails in runtime.
+ bind_error([Seg], BinType, t_none(), bind);
+ _ ->
{Map1, [SizeType]} = do_bind_pat_vars([Size], [t_non_neg_integer()],
Map, State, false, []),
Opaques = State#state.opaques,
@@ -1668,14 +1671,8 @@ bind_bin_segs([], _BinType, Acc, Map, _State) ->
bitstr_bitsize_type(Size) ->
case cerl:is_literal(Size) of
- true ->
- case cerl:concrete(Size) of
- all -> all;
- undefined -> utf;
- _ -> any
- end;
- false ->
- any
+ true -> {literal, cerl:concrete(Size)};
+ false -> variable
end.
%% Return the infimum (meet) of ExpectedType and Type if it describes a
diff --git a/lib/dialyzer/src/dialyzer_options.erl b/lib/dialyzer/src/dialyzer_options.erl
index 73a1bbb589..de35f5f204 100644
--- a/lib/dialyzer/src/dialyzer_options.erl
+++ b/lib/dialyzer/src/dialyzer_options.erl
@@ -18,7 +18,7 @@
-module(dialyzer_options).
--export([build/1, build_warnings/2]).
+-export([build/1, build_warnings/2, get_default_config_filename/0]).
-include("dialyzer.hrl").
@@ -48,9 +48,12 @@ build(Opts) ->
?WARN_UNDEFINED_CALLBACK,
?WARN_UNKNOWN],
DefaultWarns1 = ordsets:from_list(DefaultWarns),
- DefaultOpts = #options{},
- DefaultOpts1 = DefaultOpts#options{legal_warnings = DefaultWarns1},
try
+ WarningsFromConfig = proplists:get_value(warnings, get_config(), []),
+ update_path_from_config(),
+ DefaultWarns2 = build_warnings(WarningsFromConfig, DefaultWarns1),
+ DefaultOpts = #options{},
+ DefaultOpts1 = DefaultOpts#options{legal_warnings = DefaultWarns2},
Opts1 = preprocess_opts(Opts),
Env = env_default_opts(),
ErrLoc = proplists:get_value(error_location, Env, ?ERROR_LOCATION),
@@ -61,6 +64,31 @@ build(Opts) ->
throw:{dialyzer_options_error, Msg} -> {error, Msg}
end.
+update_path_from_config() ->
+ Config = get_config(),
+ PAs = proplists:get_value(add_pathsa, Config, []),
+ PZs = proplists:get_value(add_pathsz, Config, []),
+ case is_list(PAs) of
+ true -> ok;
+ false -> bad_option("Bad list of paths in config", {add_pathsa, PAs})
+ end,
+ case is_list(PZs) of
+ true -> ok;
+ false -> bad_option("Bad list of paths in config", {add_pathsz, PZs})
+ end,
+ %% Add paths one-by-one so that we can report issues
+ %% if any path is invalid
+ %% (code:add_pathsa/1 and code:add_pathsz/1 always return ok)
+ [ case code:add_patha(PA) of
+ true -> ok;
+ {error, _} -> bad_option("Failed to add path from config", {add_patha, PA})
+ end || PA <- PAs ],
+ [ case code:add_pathz(PZ) of
+ true -> ok;
+ {error, _} -> bad_option("Failed to add path from config", {add_pathz, PZ})
+ end || PZ <- PZs ],
+ ok.
+
preprocess_opts([]) -> [];
preprocess_opts([{init_plt, File}|Opts]) ->
[{plts, [File]}|preprocess_opts(Opts)];
@@ -79,7 +107,7 @@ postprocess_opts(Opts = #options{}) ->
check_module_lookup_file_validity(Opts1),
Opts2 = check_output_plt(Opts1),
check_init_plt_kind(Opts2),
- Opts3 = manage_default_apps(Opts2),
+ Opts3 = manage_default_incremental_apps(Opts2),
adapt_get_warnings(Opts3).
check_metrics_file_validity(#options{analysis_type = incremental, metrics_file = none}) ->
@@ -160,31 +188,49 @@ check_init_plt_kind(#options{analysis_type = _NotIncremental, init_plts = InitPl
lists:foreach(RunCheck, InitPlts).
%% If no apps are set explicitly, we fall back to config
-manage_default_apps(Opts = #options{analysis_type = incremental, files = [], files_rec = [], warning_files = [], warning_files_rec = []}) ->
- DefaultConfig = get_default_config_filename(),
- case file:consult(DefaultConfig) of
- {ok, [{incremental, {default_apps, DefaultApps}=Term}]} when
+manage_default_incremental_apps(Opts = #options{analysis_type = incremental, files = [], files_rec = [], warning_files = [], warning_files_rec = []}) ->
+ set_default_apps(get_config(), Opts);
+manage_default_incremental_apps(Opts) ->
+ Opts.
+
+set_default_apps([ConfigElem|MoreConfig], Opts) ->
+ case ConfigElem of
+ {incremental, {default_apps, DefaultApps}=Term} when
is_list(DefaultApps) ->
AppDirs = get_app_dirs(DefaultApps),
assert_filenames_form(Term, AppDirs),
Opts#options{files_rec = AppDirs};
- {ok, [{incremental, {default_apps, DefaultApps}=TermApps,
- {default_warning_apps, DefaultWarningApps}=TermWarns}]} when
+ {incremental, {default_apps, DefaultApps}=TermApps,
+ {default_warning_apps, DefaultWarningApps}=TermWarns} when
is_list(DefaultApps), is_list(DefaultWarningApps) ->
- AppDirs = get_app_dirs(DefaultApps),
+ AppDirs = get_app_dirs(DefaultApps ++ DefaultWarningApps),
assert_filenames_form(TermApps, AppDirs),
WarningAppDirs = get_app_dirs(DefaultWarningApps),
assert_filenames_form(TermWarns, WarningAppDirs),
Opts#options{files_rec = AppDirs, warning_files_rec = WarningAppDirs};
- {ok, _Terms} ->
- bad_option("Given Erlang terms could not be understood as Dialyzer config", DefaultConfig);
- {error, Reason} ->
- bad_option(file:format_error(Reason), DefaultConfig)
+ _ when element(1, ConfigElem) =:= incremental ->
+ bad_option("Given Erlang terms in 'incremental' section could not be understood as Dialyzer config", ConfigElem);
+ _ ->
+ set_default_apps(MoreConfig, Opts)
end;
-manage_default_apps(Opts) ->
+set_default_apps([], Opts) ->
Opts.
+get_config() ->
+ DefaultConfig = get_default_config_filename(),
+ case filelib:is_regular(DefaultConfig) of
+ true ->
+ case file:consult(DefaultConfig) of
+ {ok, Config} when is_list(Config) -> Config;
+ {error, Reason} ->
+ bad_option(file:format_error(Reason), DefaultConfig)
+ end;
+ false ->
+ []
+ end.
+
% Intended to work like dialyzer_iplt:get_default_iplt_filename()
+-spec get_default_config_filename() -> string().
get_default_config_filename() ->
case os:getenv("DIALYZER_CONFIG") of
false ->
@@ -339,10 +385,31 @@ build_options([], Options) ->
Options.
get_app_dirs(Apps) when is_list(Apps) ->
- dialyzer_cl_parse:get_lib_dir([atom_to_list(A) || A <- Apps]);
+ get_lib_dir([atom_to_list(A) || A <- Apps]);
get_app_dirs(Apps) ->
bad_option("Use a list of otp applications", Apps).
+get_lib_dir(Apps) ->
+ get_lib_dir(Apps, []).
+
+get_lib_dir([H|T], Acc) ->
+ NewElem =
+ case code:lib_dir(list_to_atom(H)) of
+ {error, bad_name} -> H;
+ LibDir when H =:= "erts" -> % hack for including erts in an un-installed system
+ EbinDir = filename:join([LibDir,"ebin"]),
+ case file:read_file_info(EbinDir) of
+ {error,enoent} ->
+ filename:join([LibDir,"preloaded","ebin"]);
+ _ ->
+ EbinDir
+ end;
+ LibDir -> filename:join(LibDir,"ebin")
+ end,
+ get_lib_dir(T, [NewElem|Acc]);
+get_lib_dir([], Acc) ->
+ lists:reverse(Acc).
+
assert_filenames(Term, Files) ->
assert_filenames_form(Term, Files),
assert_filenames_exist(Files).
diff --git a/lib/dialyzer/src/typer.erl b/lib/dialyzer/src/typer.erl
index 3b88ca6282..6467ae0093 100644
--- a/lib/dialyzer/src/typer.erl
+++ b/lib/dialyzer/src/typer.erl
@@ -93,21 +93,33 @@ cl(["-I",Dir|Opts]) -> {{inc, Dir}, Opts};
cl(["-I"|_Opts]) -> fatal_error("no include directory specified after -I");
cl(["-I"++Dir|Opts]) -> {{inc, Dir}, Opts};
cl(["-T"|Opts]) ->
- {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
+ {Files, RestOpts} = collect_args(Opts),
case Files of
[] -> fatal_error("no file or directory specified after -T");
[_|_] -> {{trusted, Files}, RestOpts}
end;
cl(["-r"|Opts]) ->
- {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
+ {Files, RestOpts} = collect_args(Opts),
{{files_r, Files}, RestOpts};
cl(["-pa",Dir|Opts]) -> {{pa,Dir}, Opts};
cl(["-pz",Dir|Opts]) -> {{pz,Dir}, Opts};
cl(["-"++H|_]) -> fatal_error("unknown option -"++H);
cl(Opts) ->
- {Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
+ {Files, RestOpts} = collect_args(Opts),
{{files, Files}, RestOpts}.
+-spec collect_args([string()]) -> {[string()], [string()]}.
+
+collect_args(List) ->
+ collect_args_1(List, []).
+
+collect_args_1(["-"++_|_] = L, Acc) ->
+ {lists:reverse(Acc), L};
+collect_args_1([Arg|T], Acc) ->
+ collect_args_1(T, [Arg|Acc]);
+collect_args_1([], Acc) ->
+ {lists:reverse(Acc), []}.
+
process_def_list(L) ->
case L of
[Name, Value] ->
diff --git a/lib/dialyzer/test/incremental_SUITE.erl b/lib/dialyzer/test/incremental_SUITE.erl
index 831e718777..1bf5731db8 100644
--- a/lib/dialyzer/test/incremental_SUITE.erl
+++ b/lib/dialyzer/test/incremental_SUITE.erl
@@ -30,6 +30,8 @@
default_apps_config_xdg/1,
default_apps_config_env_var/1,
default_apps_config_env_var_prioritised_over_xdg/1,
+ legal_warnings_config_xdg/1,
+ paths_config_xdg/1,
multiple_plts_unsupported_in_incremental_mode/1]).
suite() ->
@@ -54,6 +56,8 @@ all() -> [report_new_plt_test,
default_apps_config_xdg,
default_apps_config_env_var,
default_apps_config_env_var_prioritised_over_xdg,
+ legal_warnings_config_xdg,
+ paths_config_xdg,
multiple_plts_unsupported_in_incremental_mode].
erlang_module() ->
@@ -739,7 +743,7 @@ default_apps_config_xdg(Config) ->
[{"HOME", TestHome}]
end,
- io:format("~p\n", [HomeEnv]),
+ io:format("~p~n", [HomeEnv]),
PrivDir = ?config(priv_dir, Config),
PltFile = filename:join(PrivDir, atom_to_list(?FUNCTION_NAME) ++ ".iplt"),
@@ -892,6 +896,176 @@ default_apps_config_env_var_prioritised_over_xdg(Config) ->
peer:stop(Peer).
+legal_warnings_config_xdg(Config) ->
+ TestHome = filename:join(?config(priv_dir, Config), ?FUNCTION_NAME),
+
+ %% We change the $HOME of the emulator to run this test
+ HomeEnv =
+ case os:type() of
+ {win32, _} ->
+ [Drive | Path] = filename:split(TestHome),
+ [{"APPDATA", filename:join(TestHome, "AppData")},
+ {"HOMEDRIVE", Drive},
+ {"HOMEPATH", filename:join(Path)}];
+ _ ->
+ [{"HOME", TestHome}]
+ end,
+
+ io:format("~p~n", [HomeEnv]),
+
+ {ok, Peer, Node} = ?CT_PEER(#{ env => HomeEnv }),
+
+ SrcWithImproperList = <<"
+ -module(my_improper_list_module).
+ -export([g/0]).
+
+ g() -> [a|b]. % Improper list: Last element is not the empty list
+ ">>,
+
+ {ok, BeamFileWithImproperList} =
+ compile(Config, SrcWithImproperList, my_improper_list_module, []),
+
+ AppsConfig =
+ {incremental, {default_apps, [stdlib, kernel, erts, compiler, mnesia, ftp]}},
+
+ erpc:call(
+ Node,
+ fun() ->
+ %% Find out the path of the config file
+ HomeConfigFilename =
+ filename:join(filename:basedir(user_config, "erlang"),
+ "dialyzer.config"),
+ io:format("~ts\n", [HomeConfigFilename]),
+ ok = filelib:ensure_dir(HomeConfigFilename),
+
+ %% Write configuration file
+ WarningsConfig1 =
+ {warnings, [no_unknown, no_improper_lists]},
+ ok = file:write_file(HomeConfigFilename,
+ io_lib:format("~p.~n~p.~n", [AppsConfig, WarningsConfig1])),
+ WarningsWithConfigSet =
+ dialyzer:run([{analysis_type, incremental},
+ {files, [BeamFileWithImproperList]},
+ {from, byte_code}]),
+ ?assertEqual([], WarningsWithConfigSet),
+
+ %% Write alternative configuration file
+ WarningsConfig2 =
+ {warnings, [no_unknown]},
+ ok = file:write_file(HomeConfigFilename,
+ io_lib:format("~p.~n~p.~n", [AppsConfig, WarningsConfig2])),
+ WarningsWithoutConfigSet =
+ dialyzer:run([{analysis_type, incremental},
+ {files, [BeamFileWithImproperList]},
+ {from, byte_code}]),
+ ?assertMatch([{warn_non_proper_list, _Loc, _Msg}], WarningsWithoutConfigSet)
+ end),
+
+ peer:stop(Peer).
+
+paths_config_xdg(Config) ->
+ TestHome = filename:join(?config(priv_dir, Config), ?FUNCTION_NAME),
+
+ %% We change the $HOME of the emulator to run this test
+ HomeEnv =
+ case os:type() of
+ {win32, _} ->
+ [Drive | Path] = filename:split(TestHome),
+ [{"APPDATA", filename:join(TestHome, "AppData")},
+ {"HOMEDRIVE", Drive},
+ {"HOMEPATH", filename:join(Path)}];
+ _ ->
+ [{"HOME", TestHome}]
+ end,
+
+ io:format("~p~n", [HomeEnv]),
+
+ ExtraModulesDirOrig =
+ filename:join(?config(data_dir, Config), "extra_modules"),
+ ExtraModulesDir =
+ filename:join(?config(priv_dir, Config), "extra_modules"),
+ ok = filelib:ensure_path(ExtraModulesDir),
+ ok = filelib:ensure_path(filename:join(ExtraModulesDir,"ebin")),
+ ok = filelib:ensure_path(filename:join(ExtraModulesDir,"src")),
+
+ {ok, _} =
+ file:copy(
+ filename:join([ExtraModulesDirOrig, "src", "extra_modules.app.src"]),
+ filename:join([ExtraModulesDir, "src", "extra_modules.app.src"])
+ ),
+ {ok, _} =
+ file:copy(
+ filename:join([ExtraModulesDirOrig, "src", "extra_module.erl"]),
+ filename:join([ExtraModulesDir, "src", "extra_module.erl"])
+ ),
+
+ {ok, Peer, Node} = ?CT_PEER(#{ env => HomeEnv }),
+ {ok, _} =
+ compile:file(
+ filename:join([ExtraModulesDir,"src","extra_module.erl"]),
+ [{outdir, filename:join([ExtraModulesDir,"ebin"])}, debug_info]
+ ),
+
+ AppsConfig =
+ {incremental,
+ {default_apps,
+ [stdlib,
+ kernel,
+ erts,
+ extra_modules
+ ]
+ },
+ {default_warning_apps,
+ [extra_modules % Only on path if added explicitly via config below
+ ]
+ }
+ },
+
+ WarningsConfig =
+ {warnings, [no_unknown]},
+
+ erpc:call(
+ Node,
+ fun() ->
+ %% Find out the path of the config file
+ HomeConfigFilename =
+ filename:join(filename:basedir(user_config, "erlang"),
+ "dialyzer.config"),
+ io:format("~ts~n", [HomeConfigFilename]),
+ ok = filelib:ensure_dir(HomeConfigFilename),
+
+ %% Write configuration file
+ PathConfig = {add_pathsa, [ExtraModulesDir, filename:join(ExtraModulesDir, "ebin"), filename:join(ExtraModulesDir, "src")]},
+ ok =
+ file:write_file(
+ HomeConfigFilename,
+ io_lib:format(
+ "~p.~n~p.~n~p.~n",
+ [AppsConfig, WarningsConfig, PathConfig])),
+
+ {Warnings, ModAnalyzed} =
+ % Will analyse apps from config, including the `extra_modules` app
+ % which contains a Dialyzer error
+ dialyzer:run_report_modules_analyzed([
+ {analysis_type, incremental},
+ {from, byte_code}]),
+
+ % Check we did actually analyze the module
+ ?assert(
+ lists:member(extra_module, ModAnalyzed),
+ lists:flatten(io_lib:format("Looking for 'extra_module' in ~tp~n", [ModAnalyzed]))),
+
+ % Check we got the warnings we expected from modules
+ % added to the path
+ ?assertMatch(
+ [ {warn_contract_types, {_,_}, {invalid_contract, [extra_module,f,1, {[1],true}, "(atom()) -> string()", "(integer()) -> nonempty_improper_list(integer(),3)"]}},
+ {warn_non_proper_list, {_,_}, {improper_list_constr,["3"]}}
+ ],
+ Warnings)
+ end),
+
+ peer:stop(Peer).
+
multiple_plts_unsupported_in_incremental_mode(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
BazPltFile = filename:join(PrivDir, atom_to_list(?FUNCTION_NAME) ++ "-baz.iplt"),
diff --git a/lib/dialyzer/test/incremental_SUITE_data/extra_modules/ebin/.gitignore b/lib/dialyzer/test/incremental_SUITE_data/extra_modules/ebin/.gitignore
new file mode 100644
index 0000000000..9aedd49be8
--- /dev/null
+++ b/lib/dialyzer/test/incremental_SUITE_data/extra_modules/ebin/.gitignore
@@ -0,0 +1,5 @@
+# Ignore everything in this directory
+*
+# Except this file, to force the directory to stick around
+# for the tests to later make use of
+!.gitignore
diff --git a/lib/dialyzer/test/incremental_SUITE_data/extra_modules/src/extra_module.erl b/lib/dialyzer/test/incremental_SUITE_data/extra_modules/src/extra_module.erl
new file mode 100644
index 0000000000..21bb42ee61
--- /dev/null
+++ b/lib/dialyzer/test/incremental_SUITE_data/extra_modules/src/extra_module.erl
@@ -0,0 +1,14 @@
+-module(extra_module).
+
+-export([start/2,stop/1,f/1]).
+
+start(StartType, StartArgs) ->
+ error.
+
+stop(State) ->
+ error.
+
+% Purposely broken to generate a warning if the module is loaded and analysed
+-spec f(atom()) -> string().
+f(N) when is_integer(N) ->
+ [N + 1|3].
diff --git a/lib/dialyzer/test/incremental_SUITE_data/extra_modules/src/extra_modules.app.src b/lib/dialyzer/test/incremental_SUITE_data/extra_modules/src/extra_modules.app.src
new file mode 100644
index 0000000000..01b38e4098
--- /dev/null
+++ b/lib/dialyzer/test/incremental_SUITE_data/extra_modules/src/extra_modules.app.src
@@ -0,0 +1,8 @@
+{application, extra_modules,
+ [{description, "An app with some extra modules"},
+ {vsn, "1"},
+ {modules, [extra_module]},
+ {registered, []},
+ {applications, [kernel, stdlib]},
+ {mod, {extra_module,[]}}
+ ]}.
diff --git a/lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl b/lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl
index 616d4d62bf..46c4c77d98 100644
--- a/lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl
+++ b/lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl
@@ -2644,7 +2644,7 @@ t_dets(_Config) ->
t_tracing(_Config) ->
- dbg:stop_clear(),
+ dbg:stop(),
{ok,Tracer} = dbg:tracer(process,{fun trace_collector/2, self()}),
dbg:p(self(),c),
@@ -2697,7 +2697,7 @@ t_tracing(_Config) ->
%% Check to extra messages
timeout = getmsg(Tracer),
- dbg:stop_clear(),
+ dbg:stop(),
ok.
getmsg(_Tracer) ->
diff --git a/lib/dialyzer/test/map_SUITE_data/src/map_galore.erl b/lib/dialyzer/test/map_SUITE_data/src/map_galore.erl
index 99eb73a5f6..dfb0e18b3a 100644
--- a/lib/dialyzer/test/map_SUITE_data/src/map_galore.erl
+++ b/lib/dialyzer/test/map_SUITE_data/src/map_galore.erl
@@ -2644,7 +2644,7 @@ t_dets(_Config) ->
t_tracing(_Config) ->
- dbg:stop_clear(),
+ dbg:stop(),
{ok,Tracer} = dbg:tracer(process,{fun trace_collector/2, self()}),
dbg:p(self(),c),
@@ -2697,7 +2697,7 @@ t_tracing(_Config) ->
%% Check to extra messages
timeout = getmsg(Tracer),
- dbg:stop_clear(),
+ dbg:stop(),
ok.
getmsg(_Tracer) ->
diff --git a/lib/dialyzer/test/small_SUITE_data/results/bs_segments b/lib/dialyzer/test/small_SUITE_data/results/bs_segments
new file mode 100644
index 0000000000..0c3c9a0717
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/bs_segments
@@ -0,0 +1,3 @@
+
+bs_segments.erl:6:1: Function t/1 has no local return
+bs_segments.erl:6:1: The pattern <<_>> can never match the type any()
diff --git a/lib/dialyzer/test/small_SUITE_data/results/gh_7153 b/lib/dialyzer/test/small_SUITE_data/results/gh_7153
new file mode 100644
index 0000000000..c596a89f82
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/gh_7153
@@ -0,0 +1,3 @@
+
+gh_7153.erl:4:1: Function t/1 has no local return
+gh_7153.erl:5:7: Binary construction will fail since the value field X in segment X/utf8 has type '原子'
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bs_segments.erl b/lib/dialyzer/test/small_SUITE_data/src/bs_segments.erl
new file mode 100644
index 0000000000..b1b8a2e866
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/bs_segments.erl
@@ -0,0 +1,7 @@
+-module(bs_segments).
+
+-export([t/1]).
+
+%% GH-7138: bogus segment sizes crashed the analysis.
+t(<<_:undefined>>) ->
+ ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/gh_7153.erl b/lib/dialyzer/test/small_SUITE_data/src/gh_7153.erl
new file mode 100644
index 0000000000..ef2ef3a25b
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/gh_7153.erl
@@ -0,0 +1,5 @@
+-module(gh_7153).
+-export([t/1]).
+
+t(X = '原子') ->
+ <<X/utf8>>.
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index dca7ba72ef..4d6fedef61 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -69,8 +69,9 @@
{"2.2.4", [{restart_application, diameter}]}, %% 23.3.4
{"2.2.5", [{restart_application, diameter}]}, %% 24.3
{"2.2.6", [{restart_application, diameter}]}, %% 25.0
- {"2.2.7", [{restart_application, diameter}]} %% 25.1
- ],
+ {"2.2.7", [{restart_application, diameter}]}, %% 25.1
+ {"2.3", [{restart_application, diameter}]}
+],
[
{"0.9", [{restart_application, diameter}]},
{"0.10", [{restart_application, diameter}]},
@@ -120,6 +121,7 @@
{"2.2.4", [{restart_application, diameter}]},
{"2.2.5", [{restart_application, diameter}]},
{"2.2.6", [{restart_application, diameter}]},
- {"2.2.7", [{restart_application, diameter}]}
+ {"2.2.7", [{restart_application, diameter}]},
+ {"2.3", [{restart_application, diameter}]}
]
}.
diff --git a/lib/diameter/src/info/diameter_dbg.erl b/lib/diameter/src/info/diameter_dbg.erl
index 9e6eb88de4..8ad393eb82 100644
--- a/lib/diameter/src/info/diameter_dbg.erl
+++ b/lib/diameter/src/info/diameter_dbg.erl
@@ -357,7 +357,7 @@ p(T) ->
stop() ->
dbg:ctp(),
- dbg:stop_clear().
+ dbg:stop().
%% tpl/1
%% tp/1
diff --git a/lib/diameter/test/diameter_config_SUITE.erl b/lib/diameter/test/diameter_config_SUITE.erl
index 90773e8f6d..0aa0d95085 100644
--- a/lib/diameter/test/diameter_config_SUITE.erl
+++ b/lib/diameter/test/diameter_config_SUITE.erl
@@ -227,7 +227,7 @@ run(List)
try
?util:run([[[fun run/1, {F, 5000}] || F <- List]])
after
- dbg:stop_clear(),
+ dbg:stop(),
diameter:stop()
end;
diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl
index e576da0f6a..2033b60355 100644
--- a/lib/diameter/test/diameter_tls_SUITE.erl
+++ b/lib/diameter/test/diameter_tls_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/edoc/test/edoc_SUITE.erl b/lib/edoc/test/edoc_SUITE.erl
index c150ace008..d09e9a2ecb 100644
--- a/lib/edoc/test/edoc_SUITE.erl
+++ b/lib/edoc/test/edoc_SUITE.erl
@@ -24,13 +24,14 @@
%% Test cases
-export([app/1,appup/1,build_std/1,build_map_module/1,otp_12008/1,
- build_app/1, otp_14285/1, infer_module_app_test/1]).
+ build_app/1, otp_14285/1, infer_module_app_test/1,
+ module_with_feature/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app,appup,build_std,build_map_module,otp_12008, build_app, otp_14285,
- infer_module_app_test].
+ infer_module_app_test, module_with_feature].
groups() ->
[].
@@ -159,3 +160,13 @@ infer_module_app_test_({M, Beam}) ->
R2 = filelib:is_regular(BeamPath2),
R1 orelse R2
end.
+
+module_with_feature(Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ Source = filename:join(DataDir, "module_with_feature.erl"),
+ DodgerOpts = [{dir, PrivDir}],
+ ok = edoc:files([Source], DodgerOpts),
+ PreprocessOpts = [{preprocess, true}, {dir, PrivDir}],
+ ok = edoc:files([Source], PreprocessOpts),
+ ok.
diff --git a/lib/edoc/test/edoc_SUITE_data/module_with_feature.erl b/lib/edoc/test/edoc_SUITE_data/module_with_feature.erl
new file mode 100644
index 0000000000..0091b704b4
--- /dev/null
+++ b/lib/edoc/test/edoc_SUITE_data/module_with_feature.erl
@@ -0,0 +1,2 @@
+-module(module_with_feature).
+-feature(maybe_expr, enable).
diff --git a/lib/eldap/doc/src/eldap.xml b/lib/eldap/doc/src/eldap.xml
index 3e7028a431..b97bdebd16 100644
--- a/lib/eldap/doc/src/eldap.xml
+++ b/lib/eldap/doc/src/eldap.xml
@@ -549,7 +549,7 @@ Control2 = eldap:paged_result_control(PageSize, Cookie1),
</desc>
</func>
<func>
- <name since="@OTP-18480@">info(Handle) -> connection_info()</name>
+ <name since="OTP 25.3.1">info(Handle) -> connection_info()</name>
<fsummary>Returns information about the LDAP connection.
</fsummary>
<type>
diff --git a/lib/eldap/doc/src/notes.xml b/lib/eldap/doc/src/notes.xml
index 563f75e827..881c1215b4 100644
--- a/lib/eldap/doc/src/notes.xml
+++ b/lib/eldap/doc/src/notes.xml
@@ -31,6 +31,22 @@
</header>
<p>This document describes the changes made to the Eldap application.</p>
+<section><title>Eldap 1.2.11</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added a new function eldap:info/1 that returns the socket
+ and the transport protocol for the eldap connection.</p>
+ <p>
+ Own Id: OTP-18480</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eldap 1.2.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk
index 77d89248c9..a25f97cb89 100644
--- a/lib/eldap/vsn.mk
+++ b/lib/eldap/vsn.mk
@@ -1 +1 @@
-ELDAP_VSN = 1.2.10
+ELDAP_VSN = 1.2.11
diff --git a/lib/erl_interface/configure b/lib/erl_interface/configure
index af0a302228..72c01560cf 100755
--- a/lib/erl_interface/configure
+++ b/lib/erl_interface/configure
@@ -8715,7 +8715,7 @@ int
main (void)
{
- __asm__ __volatile__("isb sy" : : : "memory");
+ __asm__ __volatile__("isb sy\n" : : : "memory");
;
return 0;
@@ -8749,7 +8749,7 @@ int
main (void)
{
- char data[512]; __asm__ __volatile__("dc cvau, %0" : "r" (data) : : "memory");
+ char data[512]; __asm__ __volatile__("dc cvau, %0\n" :: "r" (data) : "memory");
;
return 0;
@@ -8783,7 +8783,7 @@ int
main (void)
{
- char data[512]; __asm__ __volatile__("ic ivau, %0" : "r" (data) : : "memory");
+ char data[512]; __asm__ __volatile__("ic ivau, %0\n" :: "r" (data) : "memory");
;
return 0;
diff --git a/lib/erl_interface/configure.ac b/lib/erl_interface/configure.ac
index 17859a339a..e660965299 100644
--- a/lib/erl_interface/configure.ac
+++ b/lib/erl_interface/configure.ac
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2022. All Rights Reserved.
+# Copyright Ericsson AB 2000-2023. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/doc/src/ei_users_guide.xml b/lib/erl_interface/doc/src/ei_users_guide.xml
index f59449c420..951fe32ad5 100644
--- a/lib/erl_interface/doc/src/ei_users_guide.xml
+++ b/lib/erl_interface/doc/src/ei_users_guide.xml
@@ -241,7 +241,7 @@ const char* node_name = "einode@durin";
const char *cookie = NULL;
short creation = time(NULL) + 1;
ei_cnode ec;
-ei_connect_init(ec,
+ei_connect_init(&ec,
node_name,
cookie,
creation); ]]></code>
@@ -257,7 +257,7 @@ ei_connect_init(ec,
<code type="none"><![CDATA[
int sockfd;
const char* node_name = "einode@durin"; /* An example */
-if ((sockfd = ei_connect(ec, nodename)) < 0)
+if ((sockfd = ei_connect(&ec, nodename)) < 0)
fprintf(stderr, "ERROR: ei_connect failed"); ]]></code>
</section>
@@ -289,7 +289,7 @@ if ((sockfd = ei_connect(ec, nodename)) < 0)
<code type="none"><![CDATA[
int pub;
-pub = ei_publish(ec, port); ]]></code>
+pub = ei_publish(&ec, port); ]]></code>
<p><c>pub</c> is a file descriptor now connected to
<c>epmd</c>. <c>epmd</c>
@@ -347,7 +347,7 @@ ei_x_encode_tuple_header(&buf, 2);
ei_x_encode_pid(&buf, ei_self(ec));
ei_x_encode_atom(&buf, "Hello world");
-ei_reg_send(ec,fd,"my_server",buf,buf.index);]]></code>
+ei_reg_send(&ec,fd,"my_server",buf,buf.index);]]></code>
<p>The first element of the tuple that is sent is your own
pid. This enables <c>my_server</c> to reply.
@@ -458,7 +458,7 @@ char **names;
int count;
int i;
-names = ei_global_names(ec,fd,&count);
+names = ei_global_names(&ec,fd,&count);
if (names)
for (i=0; i<count; i++)
@@ -487,7 +487,7 @@ ETERM *pid;
char node[256];
erlang_pid the_pid;
-if (ei_global_whereis(ec,fd,"schedule",&the_pid,node) < 0)
+if (ei_global_whereis(&ec,fd,"schedule",&the_pid,node) < 0)
fprintf(stderr, "ei_global_whereis error\n"); ]]></code>
<p>If <c>"schedule"</c> is known to the
@@ -524,7 +524,7 @@ ei_global_register(fd,servicename,ei_self(ec)); ]]></code>
<p>To unregister a name:</p>
<code type="none"><![CDATA[
-ei_global_unregister(ec,fd,servicename); ]]></code>
+ei_global_unregister(&ec,fd,servicename); ]]></code>
</section>
</chapter>
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index a1bb84f224..7bac4913ab 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -31,6 +31,22 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 5.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed configure tests for a few ARM-specific
+ instructions, which prevented the emulator from being
+ built on some platforms.</p>
+ <p>
+ Own Id: OTP-18554</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 5.3.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index e5f1c307fd..3f2becde5a 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -1058,11 +1058,11 @@ int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name,
strcpy(thishostname, hp->h_name);
}
}
- if (strlen(this_node_name) + 1 + strlen(thishostname) > MAXNODELEN) {
+ if (snprintf(thisnodename, sizeof(thisnodename), "%s@%s",
+ this_node_name, thishostname) > sizeof(thisnodename)) {
EI_TRACE_ERR0("ei_connect_init_ussi","this node name is too long");
return ERL_ERROR;
}
- sprintf(thisnodename, "%s@%s", this_node_name, thishostname);
res = ei_connect_xinit_ussi(ec, thishostname, thisalivename, thisnodename,
(struct in_addr *)*hp->h_addr_list, cookie, creation,
cbs, cbs_sz, setup_context);
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index 4548b9f4dd..1fb72c65cb 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -441,11 +441,11 @@ int main(int argc, char *argv[])
memcpy(&h_ipadr.s_addr, *hp->h_addr_list, sizeof(struct in_addr));
if (h_alivename) {
- if (strlen(h_alivename) + strlen(h_hostname) + 2 > sizeof(h_nodename_buf)) {
+ if (snprintf(h_nodename_buf, sizeof(h_nodename_buf), "%s@%s",
+ h_alivename, h_hostname) > sizeof(h_nodename_buf)) {;
fprintf(stderr,"erl_call: hostname too long: %s\n", h_hostname);
exit_free_flags_fields(1, &flags);
}
- sprintf(h_nodename, "%s@%s", h_alivename, h_hostname);
}
else {
/* dynamic node name */
@@ -490,11 +490,11 @@ int main(int argc, char *argv[])
}
if (flags.port == -1) {
- if (strlen(flags.node) + strlen(host_name) + 2 > sizeof(nodename)) {
+ if (snprintf(nodename, sizeof(nodename),
+ "%s@%s", flags.node, host_name) > sizeof(nodename)) {
fprintf(stderr,"erl_call: nodename too long: %s\n", flags.node);
exit_free_flags_fields(1, &flags);
}
- sprintf(nodename, "%s@%s", flags.node, host_name);
}
/*
* Try to connect. Start an Erlang system if the
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index badd74c6da..683e6643c7 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1,2 +1,2 @@
-EI_VSN = 5.3.1
+EI_VSN = 5.3.2
ERL_INTERFACE_VSN = $(EI_VSN)
diff --git a/lib/et/doc/src/et_intro.xml b/lib/et/doc/src/et_intro.xml
index 4c6fb6f27b..ae5bd7ffe2 100644
--- a/lib/et/doc/src/et_intro.xml
+++ b/lib/et/doc/src/et_intro.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl
index 75ed1179bf..a1b7306c63 100644
--- a/lib/et/src/et_collector.erl
+++ b/lib/et/src/et_collector.erl
@@ -684,7 +684,7 @@ monitor_trace_port(CollectorPid, Parameters) ->
MonitorRef = erlang:monitor(process, CollectorPid),
receive
{'DOWN', MonitorRef, _, _, _} ->
- dbg:stop_clear()
+ dbg:stop()
end
end),
Res.
diff --git a/lib/ftp/test/ftp_SUITE.erl b/lib/ftp/test/ftp_SUITE.erl
index 843cd38b8a..c1284f6ff6 100644
--- a/lib/ftp/test/ftp_SUITE.erl
+++ b/lib/ftp/test/ftp_SUITE.erl
@@ -1084,7 +1084,7 @@ error_datafail(Config) ->
dbg:tpl(ftp_internal, verbose, []),
dbg:p(Pid, [call]),
{error,_} = ftp:ls(Pid),
- dbg:stop_clear(),
+ dbg:stop(),
Recv = fun(Recv) ->
receive
Msg when is_list(Msg) ->
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index e0127e1bf7..41f6271a0d 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>2022</year>
+ <year>2012</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/httpd_util.xml b/lib/inets/doc/src/httpd_util.xml
index 5f6d016f1c..f8bd403efa 100644
--- a/lib/inets/doc/src/httpd_util.xml
+++ b/lib/inets/doc/src/httpd_util.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2022</year>
+ <year>1997</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index a6d3e10620..a10ee19030 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,7 +33,33 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 8.3</title>
+ <section><title>Inets 8.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct timing related pipelining/keepalive queue bug,
+ that could result in unexpected "socket_remotly_closed"
+ errors.</p>
+ <p>
+ Own Id: OTP-18509 Aux Id: OTP-18476 </p>
+ </item>
+ <item>
+ <p>
+ With this change, upon remote socket closure current
+ request is added to a retried queue (either pipeline or
+ keep_alive, but not both).</p>
+ <p>
+ Own Id: OTP-18545 Aux Id: OTP-18509, ERIERL-937,
+ ERIERL-928 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 8.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -276,6 +302,24 @@
</section>
+ <section><title>Inets 7.5.3.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, upon remote socket closure current
+ request is added to a retried queue (either pipeline or
+ keep_alive, but not both).</p>
+ <p>
+ Own Id: OTP-18545 Aux Id: OTP-18509, ERIERL-937,
+ ERIERL-928 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Inets 7.5.3.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/inets/examples/server_root/Makefile b/lib/inets/examples/server_root/Makefile
index ad8a4758eb..ccce663881 100644
--- a/lib/inets/examples/server_root/Makefile
+++ b/lib/inets/examples/server_root/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2022. All Rights Reserved.
+# Copyright Ericsson AB 1997-2023. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/inets/examples/server_root/conf/httpd.conf b/lib/inets/examples/server_root/conf/httpd.conf
index 62043b5aa1..d74e00bf4a 100644
--- a/lib/inets/examples/server_root/conf/httpd.conf
+++ b/lib/inets/examples/server_root/conf/httpd.conf
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index b4315f4ba3..8f62b8906c 100644
--- a/lib/inets/src/http_client/httpc.erl
+++ b/lib/inets/src/http_client/httpc.erl
@@ -1009,12 +1009,14 @@ http_options_default() ->
error
end,
+ SslOpts = ssl_verify_host_options(true),
+
UrlDecodePost = boolfun(),
[
{version, {value, "HTTP/1.1"}, #http_options.version, VersionPost},
{timeout, {value, ?HTTP_REQUEST_TIMEOUT}, #http_options.timeout, TimeoutPost},
{autoredirect, {value, true}, #http_options.autoredirect, AutoRedirectPost},
- {ssl, {value, {ssl, []}}, #http_options.ssl, SslPost},
+ {ssl, {value, {ssl, SslOpts}}, #http_options.ssl, SslPost},
{proxy_auth, {value, undefined}, #http_options.proxy_auth, ProxyAuthPost},
{relaxed, {value, false}, #http_options.relaxed, RelaxedPost},
{url_encode, {value, false}, #http_options.url_encode, UrlDecodePost},
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index c3185269f1..026cea9b1f 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -292,64 +292,35 @@ handle_info(Info, State) ->
%% Function: terminate(Reason, State) -> _ (ignored by gen_server)
%% Description: Shutdown the httpc_handler
%%--------------------------------------------------------------------
-
terminate(normal, #state{session = undefined}) ->
- ok;
-
+ ok;
%% Init error sending, no session information has been setup but
%% there is a socket that needs closing.
-terminate(normal,
- #state{session = #session{id = undefined} = Session}) ->
+terminate(normal,
+ #state{session = #session{id = undefined} = Session}) ->
close_socket(Session);
-
%% Socket closed remotely
-terminate(normal,
- #state{session = #session{socket = {remote_close, Socket},
- socket_type = SocketType,
- id = Id},
- profile_name = ProfileName,
- request = Request,
- timers = Timers,
- pipeline = Pipeline,
- keep_alive = KeepAlive} = State) ->
- %% Clobber session
- (catch httpc_manager:delete_session(Id, ProfileName)),
-
- maybe_retry_queue(Pipeline, State),
- maybe_retry_queue(KeepAlive, State),
-
- %% Cancel timers
+terminate(normal, #state{session = #session{socket = {remote_close, Socket},
+ socket_type = SocketType},
+ request = Request,
+ timers = Timers} = State) ->
+ clobber_and_retry(State),
cancel_timers(Timers),
-
maybe_deliver_answer(Request, State),
-
%% And, just in case, close our side (**really** overkill)
http_transport:close(SocketType, Socket);
-
-terminate(_Reason, #state{session = #session{id = Id,
- socket = Socket,
- socket_type = SocketType},
- request = undefined,
- profile_name = ProfileName,
- timers = Timers,
- pipeline = Pipeline,
- keep_alive = KeepAlive} = State) ->
-
- %% Clobber session
- (catch httpc_manager:delete_session(Id, ProfileName)),
-
- maybe_retry_queue(Pipeline, State),
- maybe_retry_queue(KeepAlive, State),
-
+terminate(_Reason, #state{session = #session{socket = Socket,
+ socket_type = SocketType},
+ request = undefined,
+ timers = Timers} = State) ->
+ clobber_and_retry(State),
cancel_timer(Timers#timers.queue_timer, timeout_queue),
http_transport:close(SocketType, Socket);
-
-terminate(_Reason, #state{request = undefined}) ->
+terminate(_Reason, #state{request = undefined}) ->
ok;
-
-terminate(Reason, #state{request = Request} = State) ->
- NewState = maybe_send_answer(Request,
- httpc_response:error(Request, Reason),
+terminate(Reason, #state{request = Request} = State) ->
+ NewState = maybe_send_answer(Request,
+ httpc_response:error(Request, Reason),
State),
terminate(Reason, NewState#state{request = undefined}).
@@ -1725,3 +1696,17 @@ format_address({[$[|T], Port}) ->
{Address, Port};
format_address(HostPort) ->
HostPort.
+
+clobber_and_retry(#state{session = #session{id = Id,
+ type = Type},
+ profile_name = ProfileName,
+ pipeline = Pipeline,
+ keep_alive = KeepAlive} = State) ->
+ %% Clobber session
+ (catch httpc_manager:delete_session(Id, ProfileName)),
+ case Type of
+ pipeline ->
+ maybe_retry_queue(Pipeline, State);
+ _ ->
+ maybe_retry_queue(KeepAlive, State)
+ end.
diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl
index ded515267a..1c5b829134 100644
--- a/lib/inets/src/http_lib/http_uri.erl
+++ b/lib/inets/src/http_lib/http_uri.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/test/http_test_lib.erl b/lib/inets/test/http_test_lib.erl
index f647370f01..f307f8d713 100644
--- a/lib/inets/test/http_test_lib.erl
+++ b/lib/inets/test/http_test_lib.erl
@@ -27,6 +27,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
+-compile(nowarn_export_all).
dummy_server(SocketType, Inet, Extra) ->
dummy_server(self(), SocketType, Inet, Extra).
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 9e43deb598..f89b06fddd 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -73,8 +73,10 @@ groups() ->
%% process_leak_on_keepalive is depending on stream_fun_server_close
%% and it shall be the last test case in the suite otherwise cookie
%% will fail.
- {sim_http, [], only_simulated() ++ server_closing_connection() ++ [process_leak_on_keepalive]},
+ {sim_http, [], only_simulated() ++ server_closing_connection() ++
+ [process_leak_on_keepalive]},
{http_internal, [], real_requests_esi()},
+ {http_internal_minimum_bytes, [], [remote_socket_close_parallel]},
{http_unix_socket, [], simulated_unix_socket()},
{https, [], [def_ssl_opt | real_requests()]},
{sim_https, [], only_simulated()},
@@ -221,6 +223,7 @@ sim_mixed() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+ logger:set_primary_config(level, warning),
PrivDir = proplists:get_value(priv_dir, Config),
DataDir = proplists:get_value(data_dir, Config),
inets_test_lib:start_apps([inets]),
@@ -241,8 +244,6 @@ init_per_group(misc = Group, Config) ->
Inet = inet_version(),
ok = httpc:set_options([{ipfamily, Inet}]),
Config;
-
-
init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https;
Group =:= sim_mixed ->
catch crypto:stop(),
@@ -290,7 +291,7 @@ end_per_group(http_unix_socket, Config) ->
%% it, dummy server waits in gen_tcp:accept and will not process stop request
httpc:request(get, {"http://localhost/v1/kv/foo", []}, [], []),
receive
- {stopped, DummyServerPid} ->
+ {stopped, _DummyServerPid} ->
ok
end,
file:delete(?UNIX_SOCKET),
@@ -353,7 +354,8 @@ init_per_testcase(persistent_connection, Config) ->
{max_keep_alive_length, 3}], persistent),
Config;
-init_per_testcase(wait_for_whole_response, Config) ->
+init_per_testcase(Case, Config) when Case == wait_for_whole_response;
+ Case == remote_socket_close_parallel ->
ct:timetrap({seconds, 60*3}),
Config;
init_per_testcase(Case, Config) when Case == post;
@@ -384,19 +386,15 @@ end_per_testcase(Case, Config)
httpc:request(url(group_name(Config), "/just_close.html", Config)),
ok;
true ->
- ct:pal("Not cleaning up because test case status was ~p", [Status]),
+ ct:log("Not cleaning up because test case status was ~p", [Status]),
ok
end;
-
end_per_testcase(_Case, _Config) ->
ok.
-
-
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-
head() ->
[{doc, "Test http head request against local server."}].
@@ -1055,7 +1053,7 @@ bad_response(Config) when is_list(Config) ->
{error, timeout} = httpc:request(get, {URL0, []}, [{timeout, 400},?SSL_NO_VERIFY], []),
{error, Reason} = httpc:request(get, {URL1, []}, [?SSL_NO_VERIFY], []),
- ct:print("Wrong Statusline: ~p~n", [Reason]).
+ ct:log("Wrong Statusline: ~p~n", [Reason]).
%%-------------------------------------------------------------------------
timeout_redirect() ->
@@ -1104,7 +1102,7 @@ invalid_http(Config) when is_list(Config) ->
{error, {could_not_parse_as_http, _} = Reason} =
httpc:request(get, {URL, []}, [?SSL_NO_VERIFY], []),
- ct:print("Parse error: ~p ~n", [Reason]).
+ ct:log("Parse error: ~p ~n", [Reason]).
%%-------------------------------------------------------------------------
@@ -1119,7 +1117,7 @@ invalid_chunk_size(Config) when is_list(Config) ->
{error, {chunk_size, _} = Reason} =
httpc:request(get, {URL, []}, [?SSL_NO_VERIFY], []),
- ct:print("Parse error: ~p ~n", [Reason]).
+ ct:log("Parse error: ~p ~n", [Reason]).
%%-------------------------------------------------------------------------
@@ -1147,7 +1145,7 @@ relaxed(Config) when is_list(Config) ->
{error, Reason} =
httpc:request(get, {URL, []}, [{relaxed, false}, ?SSL_NO_VERIFY], []),
- ct:print("Not relaxed: ~p~n", [Reason]),
+ ct:log("Not relaxed: ~p~n", [Reason]),
{ok, {{_, 200, _}, [_ | _], [_ | _]}} =
httpc:request(get, {URL, []}, [{relaxed, true}, ?SSL_NO_VERIFY], []).
@@ -1395,7 +1393,7 @@ binary_url(Config) ->
%%-------------------------------------------------------------------------
-iolist_body(Config) ->
+iolist_body(_Config) ->
{ok, ListenSocket} = gen_tcp:listen(0, [{active,once}, binary]),
{ok,{_,Port}} = inet:sockname(ListenSocket),
@@ -1593,7 +1591,7 @@ timeout_memory_leak(Config) when is_list(Config) ->
{error, timeout} ->
%% And now we check the size of the handler db
Info = httpc:info(),
- ct:print("Info: ~p", [Info]),
+ ct:log("Info: ~p", [Info]),
{value, {handlers, Handlers}} =
lists:keysearch(handlers, 1, Info),
case Handlers of
@@ -1786,7 +1784,7 @@ stream_fun_server_close(Config) when is_list(Config) ->
{ok, RequestId} = httpc:request(get, Request, [], [{sync, false}, {receiver, Fun}]),
receive
{RequestId, {error, Reason}} ->
- ct:pal("Close ~p", [Reason]),
+ ct:log("Close ~p", [Reason]),
ok
after 13000 ->
ct:fail(did_not_receive_close)
@@ -1911,6 +1909,82 @@ def_ssl_opt(_Config) ->
{'EXIT', _} = catch httpc:ssl_verify_host_options(other),
ok.
+%%-------------------------------------------------------------------------
+remote_socket_close_parallel() ->
+ [{doc,
+ "Verify remote socket closure (related tickets: OTP-18509, OTP-18545,"
+ "ERIERL-937). Transferred data size needs to be significant, so that "
+ "socket is closed, in the middle of a transfer."
+ "Note: test case is require good network and CPU - due to that "
+ " it is not included in all()."}].
+remote_socket_close_parallel(Config0) when is_list(Config0) ->
+ ClientNumber = 200,
+ Config = [{iterations, 10} | Config0],
+ ClientPids =
+ [spawn(?MODULE, connect, [self(), [{client_id, Id} | Config]]) ||
+ Id <- lists:seq(1, ClientNumber)],
+ ct:log("Started ~p clients: ~w", [ClientNumber, ClientPids]),
+ Receive = fun(S) ->
+ receive
+ ok ->
+ ct:log("++ Client finished (~p)", [S]),
+ ok;
+ Other ->
+ ct:fail(Other)
+ end
+ end,
+ [ok = Receive(S) || S <- lists:seq(1, ClientNumber)],
+ ok.
+
+connect(From, Config) ->
+ From ! loop(?config(iterations, Config),
+ io_lib:format("C~p|", [?config(client_id, Config)]),
+ Config).
+
+loop(0, Acc, _Config) ->
+ ct:log("~n~s|", [Acc]),
+ ok;
+loop(Cnt, Acc, Config) ->
+ case request(Config) of
+ {ok, {{_,200,"OK"}, _, _}} ->
+ case process_info(self(), message_queue_len) of
+ {message_queue_len,0} ->
+ loop(Cnt-1, Acc ++ ".", Config);
+ _ ->
+ %% queue is expected to be empty
+ queue_check(),
+ ct:pal("~n~s|", [Acc ++ "x"]),
+ fail
+ end;
+ {ok, NotOk} ->
+ ct:pal("200 OK was not received~n~p", [NotOk]),
+ fail;
+ Error ->
+ ct:pal("Error: ~p",[Error]),
+ fail
+ end.
+
+queue_check() ->
+ receive
+ {http, {ReqId, {_Result, _Head, Data}}} when is_binary(Data) ->
+ ct:pal("Unexpected data received: ~p ",
+ [ReqId]),
+ queue_check();
+ X ->
+ ct:pal("Caught unexpected something else: ~p",[X]),
+ queue_check()
+ after 5000 ->
+ done
+ end.
+
+request(Config) ->
+ Request = {url(group_name(Config), "/httpc_SUITE/foo", Config), []},
+ httpc:request(get, Request, [],[{sync,true}, {body_format,binary}]).
+
+foo(SID, _Env, _Input) ->
+ EightyMillionBits = 80000000, %% ~10MB transferred
+ mod_esi:deliver(SID, [<<0:EightyMillionBits>>]).
+
%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
%%--------------------------------------------------------------------
@@ -2005,12 +2079,13 @@ url(https, End, Config) ->
Port = proplists:get_value(port, Config),
{ok,Host} = inet:gethostname(),
?TLS_URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End;
-url(sim_http, End, Config) ->
- url(http, End, Config);
-url(http_internal, End, Config) ->
+url(Group, End, Config) when Group == sim_http;
+ Group == http_internal;
+ Group == http_internal_minimum_bytes ->
url(http, End, Config);
url(sim_https, End, Config) ->
url(https, End, Config).
+
url(http, UserInfo, End, Config) ->
Port = proplists:get_value(port, Config),
?URL_START ++ UserInfo ++ integer_to_list(Port) ++ End;
@@ -2075,39 +2150,32 @@ server_start(_, HttpdConfig) ->
{value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv),
proplists:get_value(port, Info).
-server_config(http, Config) ->
+server_config(base, Config) ->
ServerRoot = proplists:get_value(server_root, Config),
[{port, 0},
{server_name,"httpc_test"},
{server_root, ServerRoot},
{document_root, proplists:get_value(doc_root, Config)},
- {bind_address, any},
- {ipfamily, inet_version()},
- {mime_type, "text/plain"},
- {script_alias, {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}}
- ];
-server_config(http_ipv6, Config) ->
+ {mime_type, "text/plain"}];
+server_config(base_http, Config) ->
ServerRoot = proplists:get_value(server_root, Config),
- [{port, 0},
- {server_name,"httpc_test"},
- {server_root, ServerRoot},
- {document_root, proplists:get_value(doc_root, Config)},
- {bind_address, {0,0,0,0,0,0,0,1}},
- {ipfamily, inet6},
- {mime_type, "text/plain"},
- {script_alias, {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}}
- ];
+ server_config(base, Config) ++
+ [{script_alias,
+ {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}}];
+server_config(http, Config) ->
+ server_config(base_http, Config) ++
+ [{bind_address, any},
+ {ipfamily, inet_version()}];
+server_config(http_ipv6, Config) ->
+ server_config(base_http, Config) ++
+ [{bind_address, {0,0,0,0,0,0,0,1}},
+ {ipfamily, inet6}];
server_config(http_internal, Config) ->
- ServerRoot = proplists:get_value(server_root, Config),
- [{port, 0},
- {server_name,"httpc_test"},
- {server_root, ServerRoot},
- {document_root, proplists:get_value(doc_root, Config)},
- {bind_address, any},
- {ipfamily, inet_version()},
- {mime_type, "text/plain"},
- {erl_script_alias, {"", [httpc_SUITE]}}
- ];
+ server_config(http, Config) ++
+ [{erl_script_alias, {"", [httpc_SUITE]}}];
+server_config(http_internal_minimum_bytes, Config) ->
+ server_config(http_internal, Config) ++
+ [{minimum_bytes_per_second, 100}];
server_config(https, Config) ->
[{socket_type, {ssl, ssl_config(Config)}} | server_config(http, Config)];
server_config(sim_https, Config) ->
@@ -2115,7 +2183,6 @@ server_config(sim_https, Config) ->
server_config(http_unix_socket, _Config) ->
Socket = ?UNIX_SOCKET,
[{unix_socket, Socket}];
-
server_config(_, _) ->
[].
@@ -2184,7 +2251,7 @@ keep_alive_requests(Request, Profile) ->
httpc:request(get, Request, [?SSL_NO_VERIFY], [{sync, false}], Profile),
ok = httpc:cancel_request(RequestIdB1, Profile),
- ct:print("Cancel ~p~n", [RequestIdB1]),
+ ct:log("Cancel ~p~n", [RequestIdB1]),
receive_replys([RequestIdB0, RequestIdB2]).
@@ -2352,7 +2419,7 @@ handle_request(Module, Function, Args, Socket) ->
end.
handle_http_msg({Method, RelUri, _, {_, Headers}, Body}, Socket, _) ->
- ct:print("Request: ~p ~p", [Method, RelUri]),
+ ct:log("Request: ~p ~p", [Method, RelUri]),
NextRequest =
case RelUri of
@@ -2399,9 +2466,9 @@ handle_http_msg({Method, RelUri, _, {_, Headers}, Body}, Socket, _) ->
_ when is_list(Msg) orelse is_binary(Msg) ->
case Msg of
[] ->
- ct:print("Empty Msg", []);
+ ct:log("Empty Msg", []);
_ ->
- ct:print("Response: ~p", [Msg]),
+ ct:log("Response: ~p", [Msg]),
send(Socket, Msg)
end
end,
@@ -2461,10 +2528,10 @@ content_type_header([_|T]) ->
handle_auth("Basic " ++ UserInfo, Challenge, DefaultResponse) ->
case string:tokens(base64:decode_to_string(UserInfo), ":") of
["alladin", "sesame"] = Auth ->
- ct:print("Auth: ~p~n", [Auth]),
+ ct:log("Auth: ~p~n", [Auth]),
DefaultResponse;
Other ->
- ct:print("UnAuth: ~p~n", [Other]),
+ ct:log("UnAuth: ~p~n", [Other]),
Challenge
end.
@@ -2977,7 +3044,7 @@ receive_streamed_body(RequestId, Body) ->
receive_streamed_body(RequestId, Body, Pid) ->
httpc:stream_next(Pid),
- ct:print("~p:receive_streamed_body -> requested next stream ~n", [?MODULE]),
+ ct:log("~p:receive_streamed_body -> requested next stream ~n", [?MODULE]),
receive
{http, {RequestId, stream, BinBodyPart}} ->
%% Make sure the httpc hasn't sent us the next 'stream'
@@ -3033,19 +3100,19 @@ run_clients(NumClients, ServerPort, SeqNumServer) ->
fun() ->
case httpc:request(Url) of
{ok, {{_,200,_}, _, Resp}} ->
- ct:print("[~w] 200 response: "
+ ct:log("[~w] 200 response: "
"~p~n", [Id, Resp]),
case lists:prefix(Req++"->", Resp) of
true -> exit(normal);
false -> exit({bad_resp,Req,Resp})
end;
{ok, {{_,EC,Reason},_,Resp}} ->
- ct:print("[~w] ~w response: "
+ ct:pal("[~w] ~w response: "
"~s~n~s~n",
[Id, EC, Reason, Resp]),
exit({bad_resp,Req,Resp});
Crap ->
- ct:print("[~w] bad response: ~p",
+ ct:pal("[~w] bad response: ~p",
[Id, Crap]),
exit({bad_resp, Req, Crap})
end
@@ -3123,14 +3190,14 @@ loop_client(N, CSock, SeqNumServer) ->
Response = lists:flatten(io_lib:format("~s->resp~3..0w/~2..0w", [ReqNum, RespSeqNum, N])),
Txt = lists:flatten(io_lib:format("Slow server (~p) got ~p, answering with ~p",
[self(), Req, Response])),
- ct:print("~s...~n", [Txt]),
+ ct:log("~s...~n", [Txt]),
slowly_send_response(CSock, Response),
case parse_connection_type(Req) of
keep_alive ->
- ct:print("~s...done~n", [Txt]),
+ ct:log("~s...done~n", [Txt]),
loop_client(N+1, CSock, SeqNumServer);
close ->
- ct:print("~s...done (closing)~n", [Txt]),
+ ct:log("~s...done (closing)~n", [Txt]),
gen_tcp:close(CSock)
end
end.
@@ -3180,7 +3247,7 @@ otp_8739(Config) when is_list(Config) ->
{error, timeout} ->
%% And now we check the size of the handler db
Info = httpc:info(),
- ct:print("Info: ~p", [Info]),
+ ct:log("Info: ~p", [Info]),
{value, {handlers, Handlers}} =
lists:keysearch(handlers, 1, Info),
case Handlers of
@@ -3247,7 +3314,7 @@ receive_stream_n(Ref, N) ->
{http, {Ref, stream_start, _}} ->
receive_stream_n(Ref, N);
{http, {Ref,stream, Data}} ->
- ct:pal("Data: ~p", [Data]),
+ ct:log("Data: ~p", [Data]),
receive_stream_n(Ref, N-1)
end.
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index b773459b95..df628257ec 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -395,7 +395,7 @@ dbg(Case, Config, Status) ->
Config;
'end' ->
io:format("dbg: stopped~n"),
- dbg:stop_clear(),
+ dbg:stop(),
ok
end;
false ->
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index c5c292cf4f..324832ca21 100644
--- a/lib/inets/test/inets_test_lib.erl
+++ b/lib/inets/test/inets_test_lib.erl
@@ -26,6 +26,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
+-compile(nowarn_export_all).
%% -- Misc os command and stuff
diff --git a/lib/inets/test/make_certs.erl b/lib/inets/test/make_certs.erl
index 7215a59823..71f508fc61 100644
--- a/lib/inets/test/make_certs.erl
+++ b/lib/inets/test/make_certs.erl
@@ -20,6 +20,7 @@
-module(make_certs).
-compile([export_all]).
+-compile(nowarn_export_all).
%-export([all/1, all/2, rootCA/2, intermediateCA/3, endusers/3, enduser/3, revoke/3, gencrl/2, verify/3]).
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 99285501c5..78efa696d8 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 8.3
+INETS_VSN = 8.3.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/jinterface/doc/src/jinterface_users_guide.xml b/lib/jinterface/doc/src/jinterface_users_guide.xml
index 63a5fe5d16..34e272bd8e 100644
--- a/lib/jinterface/doc/src/jinterface_users_guide.xml
+++ b/lib/jinterface/doc/src/jinterface_users_guide.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2022</year>
+ <year>2000</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/Makefile b/lib/kernel/Makefile
index 534b564c2c..7586a4c981 100644
--- a/lib/kernel/Makefile
+++ b/lib/kernel/Makefile
@@ -35,7 +35,7 @@ SPECIAL_TARGETS =
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_subdir.mk
-DIA_PLT_APPS=crypto
+DIA_PLT_APPS=crypto compiler
TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 166309731c..a1f585f5cd 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -190,7 +190,7 @@
</desc>
</func>
<func>
- <name name="get_supervisor" arity="1" since="OTP 25.1"/>
+ <name name="get_supervisor" arity="1" since="OTP @OTP-18444@"/>
<fsummary>Get the supervisor of an application.</fsummary>
<desc>
<p>Returns the <c><anno>Pid</anno></c> of the supervisor running
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 1bc90f1e8b..ffa77641de 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -427,7 +427,7 @@ zip:create("mnesia-4.4.7.ez",
</func>
<func>
<name name="add_pathsa" arity="1" since=""/>
- <name name="add_pathsa" arity="2" since=""/>
+ <name name="add_pathsa" arity="2" since="OTP @OTP-18466@"/>
<fsummary>Add directories to the beginning of the code path.</fsummary>
<desc>
<p>Traverses <c><anno>Dirs</anno></c> and adds
diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml
index a7209f3f07..dc6f9ba5bf 100644
--- a/lib/kernel/doc/src/disk_log.xml
+++ b/lib/kernel/doc/src/disk_log.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1997</year>
- <year>2021</year>
+ <year>2023</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -713,7 +713,7 @@
</desc>
</func>
<func>
- <name name="next_file" arity="1" since=""/>
+ <name name="next_file" arity="1" since="OTP @OTP-18331@"/>
<fsummary>Change to the next log file of a disk log.</fsummary>
<type name="next_file_error_rsn"/>
<type name="invalid_header"/>
diff --git a/lib/kernel/doc/src/erpc.xml b/lib/kernel/doc/src/erpc.xml
index 3f8664bae0..1c5ac214b0 100644
--- a/lib/kernel/doc/src/erpc.xml
+++ b/lib/kernel/doc/src/erpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2022</year>
+ <year>2020</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml
index 4fe9b6535e..c5b110f2e5 100644
--- a/lib/kernel/doc/src/rpc.xml
+++ b/lib/kernel/doc/src/rpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2022</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/doc/src/socket.xml b/lib/kernel/doc/src/socket.xml
index e8e77b8295..2861108da6 100644
--- a/lib/kernel/doc/src/socket.xml
+++ b/lib/kernel/doc/src/socket.xml
@@ -148,69 +148,8 @@
<c>Info</c> will be <c>{SelectHandle, closed}</c>. </p>
</note>
- <marker id="asynchronous-call"/>
<note>
- <p>OLD NOTE</p>
- <p>Select-based <i>asynchronous</i> message interface. </p>
- <p>
- Some functions allow for an <i>asynchronous</i> call.
- This is achieved by setting the <c>Timeout</c> argument to
- <c>nowait</c>.
- For instance, if calling the
- <seeerl marker="#recv-nowait"><c>recv/3</c></seeerl>
- function with Timeout set to <c>nowait</c>
- (<c>recv(Sock, 0, nowait)</c>)
- when there is actually nothing to read, it will return with
- <c>{select, </c>
- <seetype marker="#select_info"><c>SelectInfo</c></seetype><c>}</c>
- (<c>SelectInfo</c> contains the
- <seetype marker="socket#select_handle">SelectHandle</seetype>).
- When data eventually arrives a 'select' message
- will be sent to the caller:
- </p>
- <taglist>
- <!-- NOTE THAT THE EMPTY TAG IS INTENTIONAL -->
- <tag></tag>
- <item><c>{'$socket', socket(), select, SelectHandle}</c></item>
- </taglist>
- <p>
- The caller can now call the <c>recv</c> function again
- and probably expect data
- (it is really up to the OS network protocol implementation).
- </p>
- <p>
- Note that all other users are <em>locked out</em> until the
- 'current user' has called the function (<c>recv</c> in this case)
- and its return value shows that the operation has completed.
- An operation can also be cancelled with
- <seemfa marker="#cancel/2"><c>cancel/2</c></seemfa>.
- </p>
- <p>
- Instead of <c>Timeout = nowait</c> it is equivalent to create a
- <seetype marker="socket#select_handle"><c>SelectHandle</c></seetype>)
- with
- <seemfa marker="erts:erlang#make_ref/0"><c>make_ref()</c></seemfa>
- and give as <c>Timeout</c>.
- This will then be the <c>SelectHandle</c> in the 'select' message,
- which enables a compiler optimization for receiving
- a message containing a newly created <c>reference()</c>
- (ignore the part of the message queue that had arrived
- before the the <c>reference()</c> was created).
- </p>
- <p>Another message the user must be prepared for (when making asynchronous
- calls) is the <c>abort</c> message:</p>
- <taglist>
- <!-- NOTE THAT THE EMPTY TAG IS INTENTIONAL -->
- <tag></tag>
- <item><c>{'$socket', socket(), abort, Info}</c></item>
- </taglist>
- <p>This message indicates
- that the (asynchronous) operation has been aborted.
- If, for instance, the socket has been closed (by another process),
- <c>Info</c> will be <c>{SelectHandle, closed}</c>. </p>
- </note>
- <note>
- <p>There is currently <em>no</em> support for Windows. </p>
+ <p>The Windows support has currently <em>pre-release</em> status. </p>
<p>Support for IPv6 has been implemented but not <em>fully</em>
tested. </p>
<p>SCTP has only been partly implemented (and not tested). </p>
@@ -1652,7 +1591,72 @@
<func>
<name name="cancel" arity="2" clause_i="1" since="OTP 22.1"/>
- <name name="cancel" arity="2" clause_i="2" since="OTP-18029"/>
+ <fsummary>Cancel an asynchronous request.</fsummary>
+ <desc>
+ <p>Cancel an asynchronous (select) request.</p>
+ <p>
+ Call this function in order to cancel a previous
+ asynchronous call to, e.g.
+ <seemfa marker="#recv/3"><c>recv/3</c></seemfa>.
+ </p>
+ <p>
+ An ongoing asynchronous operation blocks the socket
+ until the operation has been finished in good order,
+ or until it has been cancelled by this function.
+ </p>
+ <p>
+ Any other process that tries an operation
+ of the same basic type (accept / send / recv) will be
+ enqueued and notified with the regular <c>select</c>
+ mechanism for asynchronous operations
+ when the current operation and all enqueued before it
+ has been completed.
+ </p>
+ <p>
+ If <c><anno>SelectInfo</anno></c> does not match an
+ operation in progress for the calling process,
+ this function returns
+ <c>{error,&nbsp;{invalid,&nbsp;SelectInfo}}</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="cancel" arity="2" clause_i="2" since="OTP 26.0"/>
+ <fsummary>Cancel an asynchronous request.</fsummary>
+ <desc>
+ <p>Cancel an asynchronous (completion) request.</p>
+ <p>
+ Call this function in order to cancel a previous
+ asynchronous call to, e.g.
+ <seemfa marker="#recv/3"><c>recv/3</c></seemfa>.
+ </p>
+ <p>
+ An ongoing asynchronous operation blocks the socket
+ until the operation has been finished in good order,
+ or until it has been cancelled by this function.
+ </p>
+ <p>
+ Any other process that tries an operation
+ of the same basic type (accept / send / recv) will be
+ enqueued and notified with the regular <c>select</c>
+ mechanism for asynchronous operations
+ when the current operation and all enqueued before it
+ has been completed.
+ </p>
+ <p>
+ If <c><anno>CompletionInfo</anno></c> does not match an
+ operation in progress for the calling process,
+ this function returns
+ <c>{error,&nbsp;{invalid,&nbsp;CompletionInfo}}</c>.
+ </p>
+ </desc>
+ </func>
+
+ <!--
+ <func>
+ <name name="cancel" arity="2" clause_i="1" since="OTP 22.1"/>
+ <name name="cancel" arity="2" clause_i="2" since="OTP 26.0"/>
<fsummary>Cancel an asynchronous request.</fsummary>
<desc>
<p>Cancel an asynchronous request.</p>
@@ -1683,6 +1687,7 @@
</p>
</desc>
</func>
+ -->
<func>
<name name="close" arity="1" since="OTP 22.0"/>
diff --git a/lib/kernel/doc/src/socket_usage.xml b/lib/kernel/doc/src/socket_usage.xml
index e9b4c89aca..dfa551426d 100644
--- a/lib/kernel/doc/src/socket_usage.xml
+++ b/lib/kernel/doc/src/socket_usage.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2018</year><year>2021</year>
+ <year>2018</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 812127eb44..c6d8922e8f 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl
index 46c1d0e5b1..41844c03d2 100644
--- a/lib/kernel/src/disk_log.hrl
+++ b/lib/kernel/src/disk_log.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl
index c4b00d234e..5f585a4c39 100644
--- a/lib/kernel/src/disk_log_1.erl
+++ b/lib/kernel/src/disk_log_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/gen_tcp_socket.erl b/lib/kernel/src/gen_tcp_socket.erl
index 84ea036c3f..fb0f807cc1 100644
--- a/lib/kernel/src/gen_tcp_socket.erl
+++ b/lib/kernel/src/gen_tcp_socket.erl
@@ -729,8 +729,10 @@ socket_close(Socket) ->
-compile({inline, [socket_cancel/2]}).
socket_cancel(Socket, SelectInfo) ->
case socket:cancel(Socket, SelectInfo) of
- ok -> ok;
- {error, closed} -> ok
+ ok -> ok;
+ {error, closed} -> ok;
+ {error, _} = ERROR -> ERROR
+
end.
%%% ========================================================================
@@ -1575,7 +1577,7 @@ handle_event(
info = SelectInfo, from = From,
listen_socket = ListenSocket},
{P, D}) ->
- socket_cancel(ListenSocket, SelectInfo),
+ _ = socket_cancel(ListenSocket, SelectInfo),
{next_state, 'closed', {P, D},
[{reply, From, {error, timeout}}]};
handle_event(Type, Content, #accept{} = State, P_D) ->
@@ -1661,7 +1663,7 @@ handle_event(
{timeout, connect}, connect,
#connect{info = SelectInfo, from = From},
{#params{socket = Socket} = _P, _D} = P_D) ->
- socket_cancel(Socket, SelectInfo),
+ _ = socket_cancel(Socket, SelectInfo),
_ = socket_close(Socket),
{next_state, 'closed', P_D,
[{reply, From, {error, timeout}}]};
@@ -2268,11 +2270,11 @@ cleanup_close_read(P, D, State, Reason) ->
case State of
#accept{
info = SelectInfo, from = From, listen_socket = ListenSocket} ->
- socket_cancel(ListenSocket, SelectInfo),
+ _ = socket_cancel(ListenSocket, SelectInfo),
{D,
[{reply, From, {error, Reason}}]};
#connect{info = SelectInfo, from = From} ->
- socket_cancel(P#params.socket, SelectInfo),
+ _ = socket_cancel(P#params.socket, SelectInfo),
{D,
[{reply, From, {error, Reason}}]};
_ ->
@@ -2283,7 +2285,7 @@ cleanup_recv(P, D, State, Reason) ->
%% ?DBG({P#params.socket, State, Reason}),
case State of
#recv{info = SelectInfo} ->
- socket_cancel(P#params.socket, SelectInfo),
+ _ = socket_cancel(P#params.socket, SelectInfo),
cleanup_recv_reply(P, D, [], Reason);
_ ->
cleanup_recv_reply(P, D, [], Reason)
diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl
index dbcd181ef5..b7d5afcc64 100644
--- a/lib/kernel/src/inet_db.erl
+++ b/lib/kernel/src/inet_db.erl
@@ -505,7 +505,7 @@ res_check_option(nameservers, NSs) ->
res_check_option(alt_nameservers, NSs) ->
res_check_list(NSs, fun res_check_ns/1);
res_check_option(domain, Dom) ->
- Dom =:= "" orelse inet_parse:visible_string(Dom);
+ inet_parse:visible_string(Dom);
res_check_option(lookup, Methods) ->
try lists_subtract(Methods, valid_lookup()) of
[] -> true;
@@ -558,7 +558,6 @@ res_check_ns({{A,B,C,D}, Port})
when ?ip(A,B,C,D), Port band 65535 =:= Port -> true;
res_check_ns(_) -> false.
-res_check_search("") -> true;
res_check_search(Dom) -> inet_parse:visible_string(Dom).
socks_option(server) -> db_get(socks5_server);
@@ -1057,7 +1056,7 @@ handle_call(Request, From, #state{db=Db}=State) ->
end;
{set_hostname, Name} ->
- case inet_parse:visible_string(Name) of
+ case inet_parse:visible_string(Name) andalso Name =/= "" of
true ->
ets:insert(Db, {hostname, Name}),
{reply, ok, State};
diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl
index 31d759428d..9d54d2c6bd 100644
--- a/lib/kernel/src/inet_parse.erl
+++ b/lib/kernel/src/inet_parse.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -386,14 +386,9 @@ port_proto([$/ | Proto], Port) when Port =/= 0 ->
%% Check if a String is a string with visible characters #21..#7E
%% visible_string(String) -> Bool
%%
-visible_string([H|T]) ->
- is_vis1([H|T]);
-visible_string(_) ->
- false.
-
-is_vis1([C | Cs]) when C >= 16#21, C =< 16#7e -> is_vis1(Cs);
-is_vis1([]) -> true;
-is_vis1(_) -> false.
+visible_string([C | Cs]) when C >= 16#21, C =< 16#7e -> visible_string(Cs);
+visible_string([]) -> true;
+visible_string(_) -> false.
%%
%% Check if a String is a domain name according to RFC XXX.
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index f66fb00bca..0fb46332f2 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -574,12 +574,13 @@ res_getby_search(Name, [Dom | Ds], _Reason, Type, Timer) ->
QueryName =
%% Join Name and Dom with a single dot.
%% Allow Dom to be "." or "", but not to lead with ".".
- %% Do not allow Name to be "".
if
- Name =/= "" andalso (Dom =:= "." orelse Dom =:= "") ->
+ Dom =:= "."; Dom =:= "" ->
Name;
- Name =/= "" andalso hd(Dom) =/= $. ->
- Name++"."++Dom;
+ Name =/= "", hd(Dom) =/= $. ->
+ Name ++ "." ++ Dom;
+ Name =:= "", hd(Dom) =/= $. ->
+ Dom;
true ->
erlang:error({if_clause, Name, Dom})
end,
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index b95953d256..a3d983d310 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/seq_trace.erl b/lib/kernel/src/seq_trace.erl
index 6ce8118ba8..47c4355f10 100644
--- a/lib/kernel/src/seq_trace.erl
+++ b/lib/kernel/src/seq_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/src/socket.erl b/lib/kernel/src/socket.erl
index 25be82543f..02e199d088 100644
--- a/lib/kernel/src/socket.erl
+++ b/lib/kernel/src/socket.erl
@@ -4548,6 +4548,7 @@ ioctl(Socket, SetRequest, Arg1, Arg2) ->
Socket :: socket(),
SelectInfo :: select_info(),
Reason :: 'closed' | invalid();
+
(Socket, CompletionInfo) -> 'ok' | {'error', Reason} when
Socket :: socket(),
CompletionInfo :: completion_info(),
@@ -4590,14 +4591,10 @@ cancel(Socket, Info) ->
erlang:error(badarg, [Socket, Info]).
-%% What about completion? There is no way to cancel a
-%% I/O completion "request" once it has been issued.
-%% But we may still have "stuff" in our own queues,
-%% which needs to be cleared out.
cancel(SockRef, Op, Handle) ->
case prim_socket:cancel(SockRef, Op, Handle) of
select_sent ->
- flush_select_msg(SockRef, Handle),
+ _ = flush_select_msg(SockRef, Handle),
_ = flush_abort_msg(SockRef, Handle),
ok;
not_found ->
@@ -4605,6 +4602,9 @@ cancel(SockRef, Op, Handle) ->
_ = flush_abort_msg(SockRef, Handle),
invalid;
Result ->
+ %% Since we do not actually if we are using
+ %% select or completion here, so flush both...
+ _ = flush_select_msg(SockRef, Handle),
_ = flush_completion_msg(SockRef, Handle),
_ = flush_abort_msg(SockRef, Handle),
Result
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index d80201679c..dc4b6c4862 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 297c824965..7b0dbb0d2e 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
%% limitations under the License.
%%
%% %CopyrightEnd%
-%%
+%%
-module(gen_sctp_SUITE).
-include_lib("common_test/include/ct.hrl").
@@ -770,6 +770,15 @@ api_listen(Config) when is_list(Config) ->
{ok,Sb} = gen_sctp:open(Pb),
{ok,Sa} = gen_sctp:open(),
+
+ element(1, os:type()) =:= unix andalso
+ begin
+ {error, nxdomain} = gen_sctp:connect(Sa, "", 65535, []),
+ {error, nxdomain} = gen_sctp:connect(Sa, '', 65535, [])
+ end,
+ {error, nxdomain} = gen_sctp:connect(Sa, ".", 65535, []),
+ {error, nxdomain} = gen_sctp:connect(Sa, '.', 65535, []),
+
case gen_sctp:connect(Sa, localhost, Pb, []) of
{error,econnrefused} ->
{ok,{Localhost,
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index 8199e42e42..c2ab0c3df6 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1998-2023. All Rights Reserved.
+%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
@@ -14,7 +14,7 @@
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(gen_tcp_api_SUITE).
@@ -353,15 +353,22 @@ t_connect_src_port(Config) when is_list(Config) ->
%% invalid things.
t_connect_bad(Config) when is_list(Config) ->
NonExistingPort = 45638, % Not in use, I hope.
- {error, Reason1} = gen_tcp:connect(localhost, NonExistingPort,
- ?INET_BACKEND_OPTS(Config)),
- io:format("Error for connection attempt to port not in use: ~p",
- [Reason1]),
-
- {error, Reason2} = gen_tcp:connect("non-existing-host-xxx", 7,
- ?INET_BACKEND_OPTS(Config)),
- io:format("Error for connection attempt to non-existing host: ~p",
- [Reason2]),
+ t_connect_bad(Config, localhost, NonExistingPort, "port not in use"),
+ t_connect_bad(Config, "non-existing-host-xxx", 7, "non-existing host"),
+ element(1, os:type()) =:= unix andalso
+ begin
+ t_connect_bad(Config, "", 7, "empty host string"),
+ t_connect_bad(Config, '', 7, "empty host atom")
+ end,
+ t_connect_bad(Config, ".", 7, "root domain string"),
+ t_connect_bad(Config, '.', 7, "root domain atom").
+
+t_connect_bad(Config, Host, Port, Descr) ->
+ {error, Reason} =
+ gen_tcp:connect(Host, Port,?INET_BACKEND_OPTS(Config)),
+ io:format(
+ "Error for connection attempt to " ++ Descr ++ ": ~p~n",
+ [Reason]),
ok.
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index d37948db28..4aefee8a79 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 1998-2023. All Rights Reserved.
-%%
+%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
@@ -14,7 +14,7 @@
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -37,7 +37,7 @@
init_per_testcase/2, end_per_testcase/2]).
-export([
- send_to_closed/1, active_n/1,
+ send_to_closed/1, send_to_empty/1, active_n/1,
buffer_size/1, binary_passive_recv/1, max_buffer_size/1, bad_address/1,
read_packets/1, recv_poll_after_active_once/1,
open_fd/1, connect/1, reconnect/1, implicit_inet6/1,
@@ -118,6 +118,7 @@ inet_backend_socket_cases() ->
all_cases() ->
[
send_to_closed,
+ send_to_empty,
buffer_size,
binary_passive_recv,
max_buffer_size,
@@ -340,6 +341,23 @@ do_send_to_closed(Config) ->
%%-------------------------------------------------------------
+%% Send to the empty host name
+
+send_to_empty(Config) when is_list(Config) ->
+ ?TC_TRY(?FUNCTION_NAME, fun() -> do_send_to_empty(Config) end).
+
+do_send_to_empty(Config) ->
+ {ok, Sock} = ?OPEN(Config, 0),
+ element(1, os:type()) =:= unix andalso
+ begin
+ {error, nxdomain} = gen_udp:send(Sock, "", ?CLOSED_PORT, "xXx"),
+ {error, nxdomain} = gen_udp:send(Sock, '', ?CLOSED_PORT, "xXx")
+ end,
+ {error, nxdomain} = gen_udp:send(Sock, ".", ?CLOSED_PORT, "xXx"),
+ {error, nxdomain} = gen_udp:send(Sock, '.', ?CLOSED_PORT, "xXx"),
+ ok.
+
+%%-------------------------------------------------------------
%% Test that the UDP socket buffer sizes are settable
%% Test UDP buffer size setting.
@@ -1744,6 +1762,11 @@ do_connect(Config) when is_list(Config) ->
?P("sleep some"),
ct:sleep({seconds, 5}),
+ ?P("try some doomed connect targets: ~p", [P1]),
+ {error, nxdomain} = gen_udp:connect(S2, "", ?CLOSED_PORT),
+ {error, nxdomain} = gen_udp:connect(S2, '', ?CLOSED_PORT),
+ {error, nxdomain} = gen_udp:connect(S2, ".", ?CLOSED_PORT),
+ {error, nxdomain} = gen_udp:connect(S2, '.', ?CLOSED_PORT),
?P("try connect second socket to: ~p, ~p", [Addr, P1]),
ok = gen_udp:connect(S2, Addr, P1),
?P("try send on second socket"),
@@ -2616,6 +2639,10 @@ do_simple_sockaddr_send_recv(#{family := _Fam} = SockAddr, _) ->
?P("[server] send failed: ~p",
[Reason1]),
exit({skip, Reason1});
+ {error, enetunreach = Reason1} ->
+ ?P("[server] send failed: ~p",
+ [Reason1]),
+ exit({skip, Reason1});
{error, Reason1} ->
exit({send_failed, Reason1})
end
@@ -2641,6 +2668,10 @@ do_simple_sockaddr_send_recv(#{family := _Fam} = SockAddr, _) ->
?P("[server] send failed: ~p",
[Reason2]),
exit({skip, Reason2});
+ {error, enetunreach = Reason2} ->
+ ?P("[server] send failed: ~p",
+ [Reason2]),
+ exit({skip, Reason2});
{error, Reason2} ->
exit({send_failed, Reason2})
end
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 6298130a09..9061b67be1 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@
t_gethostbyaddr/0, t_gethostbyaddr/1,
t_getaddr/0, t_getaddr/1,
- t_gethostbyname/0, t_gethostbyname/1,
+ t_gethostbyname/0, t_gethostbyname/1, t_gethostbyname_empty/1,
t_gethostbyaddr_v6/0, t_gethostbyaddr_v6/1,
t_getaddr_v6/0, t_getaddr_v6/1,
t_gethostbyname_v6/0, t_gethostbyname_v6/1,
@@ -70,7 +70,7 @@ suite() ->
all() ->
[
- t_gethostbyaddr, t_gethostbyname, t_getaddr,
+ t_gethostbyaddr, t_gethostbyname, t_gethostbyname_empty, t_getaddr,
t_gethostbyaddr_v6, t_gethostbyname_v6, t_getaddr_v6,
ipv4_to_ipv6, host_and_addr, is_ip_address, {group, parse},
t_gethostnative, gethostnative_parallell, cname_loop,
@@ -367,6 +367,18 @@ do_gethostbyname(Config) when is_list(Config) ->
{error,nxdomain} = inet:gethostbyname(IP_46_Str),
ok.
+
+t_gethostbyname_empty(Config) when is_list(Config) ->
+ element(1, os:type()) =:= unix andalso
+ begin
+ {error,nxdomain} = inet:gethostbyname(""),
+ {error,nxdomain} = inet:gethostbyname('')
+ end,
+ {error,nxdomain} = inet:gethostbyname("."),
+ {error,nxdomain} = inet:gethostbyname('.'),
+ ok.
+
+
t_gethostbyname_v6() -> required(v6).
%% Test the inet:gethostbyname/1 inet6 function.
t_gethostbyname_v6(Config) when is_list(Config) ->
diff --git a/lib/kernel/test/logger_disk_log_h_SUITE.erl b/lib/kernel/test/logger_disk_log_h_SUITE.erl
index 08908b8b7a..fab125e5ae 100644
--- a/lib/kernel/test/logger_disk_log_h_SUITE.erl
+++ b/lib/kernel/test/logger_disk_log_h_SUITE.erl
@@ -674,7 +674,7 @@ sync(Config) ->
check_tracer(100),
ok.
sync(cleanup,_Config) ->
- dbg:stop_clear(),
+ dbg:stop(),
logger:remove_handler(?MODULE).
disk_log_wrap(Config) ->
@@ -720,7 +720,7 @@ disk_log_wrap(Config) ->
%% wait for trace messages
timer:sleep(1000),
- dbg:stop_clear(),
+ dbg:stop(),
Received = lists:flatmap(fun({trace,_M,handle_info,
[_,{disk_log,_Node,_Name,What},_]}) ->
[{trace,What}];
@@ -732,7 +732,7 @@ disk_log_wrap(Config) ->
ok.
disk_log_wrap(cleanup,_Config) ->
- dbg:stop_clear(),
+ dbg:stop(),
logger:remove_handler(?MODULE).
disk_log_full(Config) ->
@@ -766,7 +766,7 @@ disk_log_full(Config) ->
%% wait for trace messages
timer:sleep(2000),
- dbg:stop_clear(),
+ dbg:stop(),
Received = lists:flatmap(fun({trace,_M,handle_info,
[_,{disk_log,_Node,_Name,What},_]}) ->
[{trace,What}];
@@ -782,7 +782,7 @@ disk_log_full(Config) ->
%% {trace,{error_status,{error,{full,_}}}}] = Received,
ok.
disk_log_full(cleanup, _Config) ->
- dbg:stop_clear(),
+ dbg:stop(),
logger:remove_handler(?MODULE).
disk_log_events(_Config) ->
@@ -816,7 +816,7 @@ disk_log_events(_Config) ->
[whereis(h_proc_name()) ! E || E <- Events],
%% wait for trace messages
timer:sleep(2000),
- dbg:stop_clear(),
+ dbg:stop(),
Received = lists:map(fun({trace,_M,handle_info,
[_,Got,_]}) -> Got
end, test_server:messages_get()),
@@ -828,7 +828,7 @@ disk_log_events(_Config) ->
end, Received),
ok.
disk_log_events(cleanup, _Config) ->
- dbg:stop_clear(),
+ dbg:stop(),
logger:remove_handler(?MODULE).
write_failure(Config) ->
@@ -1603,7 +1603,7 @@ tpl([{{M,F,A},MS}|Trace]) ->
{_,_,1} ->
ok;
_ ->
- dbg:stop_clear(),
+ dbg:stop(),
throw({skip,"Can't trace "++atom_to_list(M)++":"++
atom_to_list(F)++"/"++integer_to_list(A)})
end,
@@ -1636,13 +1636,13 @@ maybe_tracer_done(Pid,Expected,Got,Caller) ->
check_tracer(T) ->
receive
tracer_done ->
- dbg:stop_clear(),
+ dbg:stop(),
ok;
{tracer_got_unexpected,Got,Expected} ->
- dbg:stop_clear(),
+ dbg:stop(),
ct:fail({tracer_got_unexpected,Got,Expected})
after T ->
- dbg:stop_clear(),
+ dbg:stop(),
ct:fail({timeout,tracer})
end.
diff --git a/lib/kernel/test/logger_std_h_SUITE.erl b/lib/kernel/test/logger_std_h_SUITE.erl
index ead4418d0d..88aac32f6f 100644
--- a/lib/kernel/test/logger_std_h_SUITE.erl
+++ b/lib/kernel/test/logger_std_h_SUITE.erl
@@ -2219,7 +2219,7 @@ tpl([]) ->
ok.
stop_clear() ->
- dbg:stop_clear(),
+ dbg:stop(),
%% Remove tracer from all processes in order to eliminate
%% race conditions.
erlang:trace(all,false,[all]).
diff --git a/lib/kernel/test/logger_stress_SUITE.erl b/lib/kernel/test/logger_stress_SUITE.erl
index 7fe12ca823..9209026322 100644
--- a/lib/kernel/test/logger_stress_SUITE.erl
+++ b/lib/kernel/test/logger_stress_SUITE.erl
@@ -343,7 +343,7 @@ cascade({PNode,PMFA,_PStatProcs},{CNode,CMFA,_CStatProcs},TestFun) ->
after TO ->
All = ets:lookup_element(Tab,producer,2),
Written = ets:lookup_element(Tab,consumer,2),
- dbg:stop_clear(),
+ dbg:stop(),
?COLLECT_STATS(All,
[{PNode,P,Id} || {Id,P} <- _PStatProcs] ++
[{CNode,P,Id} || {Id,P} <- _CStatProcs]),
diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl
index 62fcd6cfb2..196af34521 100644
--- a/lib/kernel/test/socket_SUITE.erl
+++ b/lib/kernel/test/socket_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -744,8 +744,11 @@
-define(TPP_LARGE_NUM, 50).
-define(TPP_NUM(Config, Base), (Base) div lookup(kernel_factor, 1, Config)).
+-define(WINDOWS, {win32,nt}).
+
-define(TTEST_RUNTIME, ?SECS(1)).
-define(TTEST_MIN_FACTOR, 3).
+-define(TTEST_MIN_FACTOR_WIN, ?TTEST_MIN_FACTOR-1).
-define(TTEST_DEFAULT_SMALL_MAX_OUTSTANDING, 50).
-define(TTEST_DEFAULT_MEDIUM_MAX_OUTSTANDING,
?TTEST_MK_DEFAULT_MAX_OUTSTANDING(
@@ -1404,7 +1407,12 @@ traffic_pp_sendmsg_recvmsg_cases() ->
%% No point in running these cases unless the machine is
%% reasonably fast.
ttest_condition(Config) ->
+ OsType = os:type(),
case ?config(kernel_factor, Config) of
+ Factor when (OsType =:= ?WINDOWS) andalso
+ is_integer(Factor) andalso
+ (Factor =< ?TTEST_MIN_FACTOR_WIN) ->
+ ok;
Factor when is_integer(Factor) andalso (Factor =< ?TTEST_MIN_FACTOR) ->
ok;
Factor when is_integer(Factor) ->
@@ -3492,7 +3500,10 @@ api_b_send_and_recv_seqpL(_Config) when is_list(_Config) ->
api_b_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_b_sendmsg_and_recvmsg_tcp4,
- fun() -> has_support_ipv4() end,
+ fun() ->
+ is_not_windows(),
+ has_support_ipv4()
+ end,
fun() ->
Send = fun(Sock, Data) ->
Msg = #{iov => [Data]},
@@ -6926,7 +6937,8 @@ api_a_connect_tcp(InitState) ->
{ok, State#{asynch_tag => select,
connect_tag => ST}};
- {completion, {completion_info, CT, CompletionRef}}
+ {completion,
+ {completion_info, CT, CompletionRef}}
when SR =:= nowait ->
?SEV_IPRINT("completion nowait ->"
"~n tag: ~p"
@@ -6935,7 +6947,8 @@ api_a_connect_tcp(InitState) ->
{ok, State#{asynch_tag => completion,
connect_tag => CT,
connect_ref => CompletionRef}};
- {completion, {completion_info, CT, CR}}
+ {completion,
+ {completion_info, CT, CR}}
when is_reference(CR) ->
?SEV_IPRINT("completion ref ->"
"~n tag: ~p"
@@ -7988,7 +8001,10 @@ api_a_sendmsg_and_recvmsg_tcp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
tc_try(api_a_sendmsg_and_recvmsg_tcp4,
- fun() -> has_support_ipv4() end,
+ fun() ->
+ is_not_windows(),
+ has_support_ipv4()
+ end,
fun() ->
Send = fun(Sock, Data) ->
Msg = #{iov => [Data]},
@@ -9488,6 +9504,7 @@ api_a_recv_cancel_tcp(InitState) ->
cmd => fun(#{tester := Tester} = _State) ->
?SEV_AWAIT_CONTINUE(Tester, tester, recv)
end},
+
#{desc => "try recv request (with nowait, expect select|completion)",
cmd => fun(#{csock := Sock,
recv := Recv,
@@ -9506,13 +9523,15 @@ api_a_recv_cancel_tcp(InitState) ->
"~n Ref: ~p", [T, Ref]),
{ok, State#{recv_select_info => SI}};
- {completion, {completion_info, T, R} = CI}
+ {completion,
+ {completion_info, T, R} = CI}
when Ref =:= nowait ->
?SEV_IPRINT("recv completion nowait: "
"~n Tag: ~p"
"~n Ref: ~p", [T, R]),
{ok, State#{recv_completion_info => CI}};
- {completion, {completion_info, T, Ref} = CI}
+ {completion,
+ {completion_info, T, Ref} = CI}
when is_reference(Ref) ->
?SEV_IPRINT("recv completion ref: "
"~n Tag: ~p"
@@ -10913,6 +10932,7 @@ api_a_mrecvmsg_cancel_tcp4(Config) when is_list(Config) ->
Nowait = nowait(Config),
tc_try(?FUNCTION_NAME,
fun() ->
+ is_not_windows(),
has_support_ipv4()
end,
fun() ->
@@ -10937,7 +10957,10 @@ api_a_mrecvmsg_cancel_tcp6(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
tc_try(?FUNCTION_NAME,
- fun() -> has_support_ipv6() end,
+ fun() ->
+ is_not_windows(),
+ has_support_ipv6()
+ end,
fun() ->
Recv = fun(Sock) ->
socket:recvmsg(Sock, Nowait)
@@ -14034,6 +14057,10 @@ api_opt_sock_broadcast() ->
?SEV_IPRINT("Expected Success: "
"broadcast message sent"),
ok;
+ {error, eaddrnotavail = Reason} ->
+ ?SEV_EPRINT("Unexpected Failure: ~p => SKIP",
+ [Reason]),
+ {skip, Reason};
{error, eacces = Reason} ->
?SEV_EPRINT("Unexpected Failure: ~p => SKIP",
[Reason]),
@@ -21126,6 +21153,37 @@ api_opt_ip_recvttl_udp(InitState) ->
{skip,
?F("Cannot send with TTL: ~p", [Info])};
+ {error,
+ {completion_status,
+ #{file := File,
+ function := Function,
+ line := Line,
+ raw_info := RawInfo,
+ info := invalid_parameter = Info}}} ->
+ %% IF we can't send it the test will not work
+ ?SEV_EPRINT("Cannot send TTL: "
+ "~p => SKIP: "
+ "~n File: ~s"
+ "~n Function: ~s"
+ "~n Line: ~p"
+ "~n Raw Info: ~p",
+ [Info,
+ File, Function, Line,
+ RawInfo]),
+ (catch socket:close(SSock)),
+ (catch socket:close(DSock)),
+ {skip,
+ ?F("Cannot send with TTL: ~p", [Info])};
+ {error, {completion_status,
+ invalid_parameter = Info}} ->
+ %% IF we can't send it the test will not work
+ ?SEV_EPRINT("Cannot send TTL: "
+ "~p => SKIP", [Info]),
+ (catch socket:close(SSock)),
+ (catch socket:close(DSock)),
+ {skip,
+ ?F("Cannot send with TTL: ~p", [Info])};
+
{error, _Reason} = ERROR ->
ERROR
end
@@ -23420,7 +23478,7 @@ api_opt_ipv6_tclass_udp(InitState) ->
#{desc => "send req (to dst) (w explicit tc = 1)",
cmd => fun(#{sock_src := Sock, sa_dst := Dst, send := Send}) ->
case Send(Sock, ?BASIC_REQ, Dst, 1) of
- {error,
+ {error,
{get_overlapped_result,
#{file := File,
function := Function,
@@ -23449,6 +23507,35 @@ api_opt_ipv6_tclass_udp(InitState) ->
{skip,
?F("Cannot send with TClass: ~p", [Info])};
+ {error,
+ {completion_status,
+ #{file := File,
+ function := Function,
+ line := Line,
+ raw_info := RawInfo,
+ info := invalid_parameter = Info}}} ->
+ %% IF we can't send it the test will not work
+ ?SEV_EPRINT("Cannot send TClass: "
+ "~p => SKIP: "
+ "~n File: ~s"
+ "~n Function: ~s"
+ "~n Line: ~p"
+ "~n Raw Info: ~p",
+ [Info,
+ File, Function, Line,
+ RawInfo]),
+ (catch socket:close(Sock)),
+ {skip,
+ ?F("Cannot send with TClass: ~p", [Info])};
+ {error, {completion_status,
+ invalid_parameter = Info}} ->
+ %% IF we can't send it the test will not work
+ ?SEV_EPRINT("Cannot send TClass: "
+ "~p => SKIP", [Info]),
+ (catch socket:close(Sock)),
+ {skip,
+ ?F("Cannot send with TClass: ~p", [Info])};
+
Other ->
Other
end
@@ -32985,8 +33072,11 @@ sc_lc_receive_response_udp(InitState) ->
sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
- tc_try(sc_lc_recvmsg_response_tcp4,
- fun() -> has_support_ipv4() end,
+ tc_try(?FUNCTION_NAME,
+ fun() ->
+ is_not_windows(),
+ has_support_ipv4()
+ end,
fun() ->
Recv = fun(Sock) -> socket:recvmsg(Sock) end,
InitState = #{domain => inet,
@@ -33003,8 +33093,11 @@ sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) ->
sc_lc_recvmsg_response_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
- tc_try(sc_recvmsg_response_tcp6,
- fun() -> has_support_ipv6() end,
+ tc_try(?FUNCTION_NAME,
+ fun() ->
+ is_not_windows(),
+ has_support_ipv6()
+ end,
fun() ->
Recv = fun(Sock) -> socket:recvmsg(Sock) end,
InitState = #{domain => inet6,
@@ -36503,7 +36596,10 @@ traffic_send_and_recv_counters_tcpL(_Config) when is_list(_Config) ->
traffic_sendmsg_and_recvmsg_counters_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_tcp4,
- fun() -> has_support_ipv4() end,
+ fun() ->
+ is_not_windows(),
+ has_support_ipv4()
+ end,
fun() ->
InitState = #{domain => inet,
proto => tcp,
@@ -36532,7 +36628,10 @@ traffic_sendmsg_and_recvmsg_counters_tcp4(_Config) when is_list(_Config) ->
traffic_sendmsg_and_recvmsg_counters_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_tcp6,
- fun() -> has_support_ipv6() end,
+ fun() ->
+ is_not_windows(),
+ has_support_ipv6()
+ end,
fun() ->
InitState = #{domain => inet6,
proto => tcp,
@@ -48842,7 +48941,7 @@ otp16359_maccept_tcp(InitState) ->
%% This test case is to verify that we do not leak monitors.
otp18240_accept_mon_leak_tcp4(Config) when is_list(Config) ->
- ?TT(?SECS(10)),
+ ?TT(?SECS(30)),
tc_try(?FUNCTION_NAME,
fun() -> has_support_ipv4() end,
fun() ->
@@ -48857,7 +48956,7 @@ otp18240_accept_mon_leak_tcp4(Config) when is_list(Config) ->
%% This test case is to verify that we do not leak monitors.
otp18240_accept_mon_leak_tcp6(Config) when is_list(Config) ->
- ?TT(?SECS(10)),
+ ?TT(?SECS(30)),
tc_try(?FUNCTION_NAME,
fun() -> has_support_ipv6() end,
fun() ->
@@ -48883,26 +48982,42 @@ otp18240_accept_tcp(#{domain := Domain,
otp18240_await_acceptor(Pid, Mon) ->
receive
- {'DOWN', Mon, process, Pid, Info} ->
- i("acceptor terminated: "
- "~n ~p", [Info])
+ {'DOWN', Mon, process, Pid, ok} ->
+ i("acceptor successfully terminated"),
+ ok;
+ {'DOWN', Mon, process, Pid, {skip, _} = SKIP} ->
+ i("acceptor successfully terminated"),
+ exit(SKIP);
+ {'DOWN', Mon, process, Pid, Info} ->
+ i("acceptor unexpected termination: "
+ "~n ~p", [Info]),
+ exit({unexpected_result, Info})
after 5000 ->
- i("acceptor info"
+ i("acceptor process (~p) info"
"~n Refs: ~p"
"~n Info: ~p",
- [monitored_by(Pid), erlang:process_info(Pid)]),
+ [Pid, monitored_by(Pid), erlang:process_info(Pid)]),
otp18240_await_acceptor(Pid, Mon)
end.
otp18240_acceptor(Parent, Domain, Proto, NumSocks) ->
i("[acceptor] begin with: "
+ "~n Parent: ~p"
"~n Domain: ~p"
- "~n Protocol: ~p", [Domain, Proto]),
+ "~n Protocol: ~p", [Parent, Domain, Proto]),
MonitoredBy0 = monitored_by(),
- {ok, LSock} = socket:open(Domain, stream, Proto,
- #{use_registry => false}),
- ok = socket:bind(LSock, #{family => Domain, port => 0, addr => any}),
+ ?SLEEP(?SECS(5)),
+ Addr = case ?LIB:which_local_host_info(Domain) of
+ {ok, #{addr := A}} ->
+ A;
+ {error, Reason} ->
+ exit({skip, Reason})
+ end,
+ {ok, LSock} = socket:open(Domain, stream, Proto,
+ #{use_registry => false}),
+ ok = socket:bind(LSock, #{family => Domain, addr => Addr, port => 0}),
ok = socket:listen(LSock, NumSocks),
+ ?SLEEP(?SECS(5)),
MonitoredBy1 = monitored_by(),
i("[acceptor]: listen socket created"
"~n 'Montored By' before listen socket: ~p"
@@ -48922,7 +49037,7 @@ otp18240_acceptor(Parent, Domain, Proto, NumSocks) ->
_Clients = [spawn_link(fun() ->
otp18240_client(CID,
Domain, Proto,
- Port)
+ Addr, Port)
end) || CID <- lists:seq(1, NumSocks)],
i("[acceptor] accept ~w connections", [NumSocks]),
@@ -48956,26 +49071,49 @@ otp18240_acceptor(Parent, Domain, Proto, NumSocks) ->
end.
-otp18240_client(ID, Domain, Proto, PortNo) ->
+otp18240_client(ID, Domain, Proto, Addr, PortNo) ->
i("[connector ~w] try create connector socket", [ID]),
{ok, Sock} = socket:open(Domain, stream, Proto, #{use_registry => false}),
- ok = socket:bind(Sock, #{family => Domain, port => 0, addr => any}),
+ ok = socket:bind(Sock, #{family => Domain, addr => Addr, port => 0}),
%% ok = socket:setopt(Sock, otp, debug, true),
i("[connector ~w] try connect", [ID]),
- ok = socket:connect(Sock, #{family => Domain, addr => any, port => PortNo}),
- i("[connector ~w] connected - now try recv", [ID]),
- case socket:recv(Sock) of
- {ok, Data} ->
- i("[connector ~w] received unexpected data: "
- "~n ~p", [ID, Data]),
- (catch socket:close(Sock)),
- exit('unexpected data');
- {error, closed} ->
- i("[connector ~w] expected socket close", [ID]);
- {error, Reason} ->
- i("[connector ~w] unexpected error when reading: "
- "~n ~p", [ID, Reason]),
- (catch socket:close(Sock))
+ case socket:connect(Sock,
+ #{family => Domain, addr => Addr, port => PortNo}) of
+ ok ->
+ i("[connector ~w] connected - now try recv", [ID]),
+ case socket:recv(Sock) of
+ {ok, Data} ->
+ i("[connector ~w] received unexpected data: "
+ "~n ~p", [ID, Data]),
+ (catch socket:close(Sock)),
+ exit('unexpected data');
+ {error, closed} ->
+ i("[connector ~w] expected socket close", [ID]);
+ {error, Reason} ->
+ i("[connector ~w] unexpected error when reading: "
+ "~n ~p", [ID, Reason]),
+ (catch socket:close(Sock))
+ end;
+ {error, {completion_status, #{info := invalid_netname = R} = Reason}} ->
+ i("[connector ~w] failed connecting: "
+ "~n ~p", [ID, Reason]),
+ (catch socket:close(Sock)),
+ exit({skip, R});
+ {error, {completion_status, invalid_netname = Reason}} ->
+ i("[connector ~w] failed connecting: "
+ "~n ~p", [ID, Reason]),
+ (catch socket:close(Sock)),
+ exit({skip, Reason});
+ {error, enetunreach = Reason} ->
+ i("[connector ~w] failed connecting: "
+ "~n ~p", [ID, Reason]),
+ (catch socket:close(Sock)),
+ exit({skip, Reason});
+
+ {error, Reason} ->
+ i("[connector ~w] failed connecting: "
+ "~n ~p", [ID, Reason]),
+ (catch socket:close(Sock))
end,
i("[connector ~w] done", [ID]),
ok.
diff --git a/lib/kernel/test/socket_test_evaluator.erl b/lib/kernel/test/socket_test_evaluator.erl
index 962c47a64e..49b529461f 100644
--- a/lib/kernel/test/socket_test_evaluator.erl
+++ b/lib/kernel/test/socket_test_evaluator.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/socket_test_lib.erl b/lib/kernel/test/socket_test_lib.erl
index 21024fd6d2..da36943461 100644
--- a/lib/kernel/test/socket_test_lib.erl
+++ b/lib/kernel/test/socket_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/kernel/test/socket_test_ttest_tcp_socket.erl b/lib/kernel/test/socket_test_ttest_tcp_socket.erl
index 467f54113a..7a084a445d 100644
--- a/lib/kernel/test/socket_test_ttest_tcp_socket.erl
+++ b/lib/kernel/test/socket_test_ttest_tcp_socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/megaco/configure.ac b/lib/megaco/configure.ac
index 82b438a5bb..8d6af651c8 100644
--- a/lib/megaco/configure.ac
+++ b/lib/megaco/configure.ac
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*-
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 2001-2021. All Rights Reserved.
+dnl Copyright Ericsson AB 2001-2023. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
diff --git a/lib/megaco/doc/src/megaco_intro.xml b/lib/megaco/doc/src/megaco_intro.xml
index 6bfe2cdec9..606ee16d5a 100644
--- a/lib/megaco/doc/src/megaco_intro.xml
+++ b/lib/megaco/doc/src/megaco_intro.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2020</year>
+ <year>2000</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/observer/doc/src/observer.xml b/lib/observer/doc/src/observer.xml
index 7454d46c9a..9185c4be0d 100644
--- a/lib/observer/doc/src/observer.xml
+++ b/lib/observer/doc/src/observer.xml
@@ -58,14 +58,14 @@
</desc>
</func>
<func>
- <name since="OTP 26">start(Node) -> ok</name>
+ <name since="OTP 26.0">start(Node) -> ok</name>
<fsummary>Start the Observer GUI connected against <c>Node</c>.</fsummary>
<desc>
<p>Starts the Observer GUI and tries to connect it to <c>Node</c>.</p>
</desc>
</func>
<func>
- <name since="OTP 26">start_and_wait() -> ok</name>
+ <name since="OTP 26.0">start_and_wait() -> ok</name>
<fsummary>Start the Observer GUI blocking.</fsummary>
<desc>
<p>Starts the Observer GUI and only return when it is either stopped or
@@ -73,7 +73,7 @@
</desc>
</func>
<func>
- <name since="OTP 26">start_and_wait(Node) -> ok</name>
+ <name since="OTP 26.0">start_and_wait(Node) -> ok</name>
<fsummary>Start the Observer GUI blocking and connect it to <c>Node</c>.</fsummary>
<desc>
<p>Starts the Observer GUI and only return when it is either stopped or
@@ -83,7 +83,7 @@
</desc>
</func>
<func>
- <name since="OTP 26">stop() -> ok</name>
+ <name since="OTP 26.0">stop() -> ok</name>
<fsummary>Stop the Observer GUI.</fsummary>
<desc>
<p>Stops the Observer GUI.</p>
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index 18789faf38..409fd4fcbb 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -508,10 +508,10 @@ handle_info(_Info, State) ->
{noreply, State}.
stop_servers(#state{node=Node, log=LogOn, panels=Panels} = _State) ->
- LogOn andalso rpc:block_call(Node, rb, stop, []),
Me = self(),
- save_config(Panels),
Stop = fun() ->
+ LogOn andalso rpc:block_call(Node, rb, stop, []),
+ save_config(Panels),
try
_ = [wx_object:stop(Panel) || {_, Panel, _} <- Panels],
ok
diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl
index c4161f4e2a..e7a1ae164f 100644
--- a/lib/observer/src/ttb.erl
+++ b/lib/observer/src/ttb.erl
@@ -784,7 +784,7 @@ do_stop(nofetch, Sender, NodeInfo, SessionInfo) ->
ok,
NodeInfo),
stop_ip_to_file_trace_ports(SessionInfo),
- dbg:stop_clear(),
+ dbg:stop(),
ets:delete(?history_table),
Sender ! {?MODULE, stopped};
@@ -807,7 +807,7 @@ do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) ->
[],
NodeInfo),
stop_ip_to_file_trace_ports(SessionInfo),
- dbg:stop_clear(),
+ dbg:stop(),
AllNodes =
lists:map(
fun({Node,MetaFile}) ->
@@ -1055,7 +1055,7 @@ format(Files,Out,Handler,DisableSort) when is_list(Files), is_list(hd(Files)) ->
file:close(Fd),
ets:delete(?MODULE),
case StopDbg of
- true -> dbg:stop_clear();
+ true -> dbg:stop();
false -> ok
end,
R.
diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c
index 604f723803..e99f16624e 100644
--- a/lib/odbc/c_src/odbcserver.c
+++ b/lib/odbc/c_src/odbcserver.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lib/odbc/configure.ac b/lib/odbc/configure.ac
index 03b252816c..febdd044a5 100644
--- a/lib/odbc/configure.ac
+++ b/lib/odbc/configure.ac
@@ -1,7 +1,7 @@
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 2005-2021. All Rights Reserved.
+dnl Copyright Ericsson AB 2005-2023. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
diff --git a/lib/os_mon/c_src/cpu_sup.c b/lib/os_mon/c_src/cpu_sup.c
index e8a9cb9d61..fd04d35987 100644
--- a/lib/os_mon/c_src/cpu_sup.c
+++ b/lib/os_mon/c_src/cpu_sup.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,6 +87,11 @@ typedef struct {
#define CU_BSD_VALUES (6)
#endif
+#if defined(__OpenBSD__)
+#include <sys/types.h>
+#include <sys/sched.h>
+#define CU_OPENBSD_VALUES (6)
+#endif
#define FD_IN (0)
#define FD_OUT (1)
@@ -178,12 +183,17 @@ static int processors_online() {
void getsysctl(const char *, void *, size_t);
#endif
+#if defined(__OpenBSD__)
+static int getncpu(void);
+static int getncpuonline(void);
+#endif
+
int main(int argc, char** argv) {
char cmd;
int rc;
int sz;
unsigned int *rv;
-#if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) ||defined(__FreeBSD__)
+#if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__OpenBSD__)
unsigned int no_of_cpus = 0;
#endif
@@ -207,6 +217,15 @@ int main(int argc, char** argv) {
}
#endif
+#if defined(__OpenBSD__)
+ no_of_cpus = getncpu();
+ if ( no_of_cpus == -1 )
+ error("cpu_sup: sysctl error");
+
+ if ( (rv = (unsigned int*)malloc(sizeof(unsigned int)*(2 + 2*no_of_cpus*CU_OPENBSD_VALUES))) == NULL)
+ error("cpu_sup: malloc error");
+#endif
+
#if defined(__FreeBSD__)
getsysctl("hw.ncpu", &no_of_cpus, sizeof(int));
if ( (rv = (unsigned int*)malloc(sizeof(unsigned int)*(2 + 2*no_of_cpus*CU_BSD_VALUES))) == NULL) {
@@ -244,7 +263,7 @@ int main(int argc, char** argv) {
case AVG5: bsd_loadavg(1); break;
case AVG15: bsd_loadavg(2); break;
#endif
-#if defined(__sun__) || defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
+#if defined(__sun__) || defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__OpenBSD__)
case UTIL: util_measure(&rv,&sz); sendv(rv, sz); break;
#endif
case QUIT: free((void*)rv); return 0;
@@ -713,6 +732,71 @@ static void util_measure(unsigned int **result_vec, int *result_sz) {
}
#endif
+/* ---------------------------- *
+ * OpenBSD stat functions *
+ * ---------------------------- */
+
+#if defined(__OpenBSD__)
+static int getncpu(void) {
+ const int mib[] = { CTL_HW, HW_NCPU };
+ int numcpu;
+ size_t size = sizeof(numcpu);
+
+ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &numcpu, &size, NULL, 0) == -1)
+ error("cpu_sup: sysctl error");
+
+ return(numcpu);
+}
+
+static int getncpuonline(void) {
+ const int mib[] = { CTL_HW, HW_NCPUONLINE };
+ int numcpu;
+ size_t size = sizeof(numcpu);
+
+ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &numcpu, &size, NULL, 0) == -1)
+ error("cpu_sup: sysctl error");
+
+ return(numcpu);
+}
+
+static void util_measure(unsigned int **result_vec, int *result_sz) {
+ static int mib[] = { CTL_KERN, KERN_CPTIME2, 0 };
+ size_t size_cpu_times;
+ int64_t *cpu_times;
+ unsigned int *rv = NULL;
+ int i;
+ int ncpuonline = getncpuonline();
+
+ rv = *result_vec;
+ rv[0] = ncpuonline;
+ rv[1] = CU_OPENBSD_VALUES;
+ ++rv; /* first value is number of cpus */
+ ++rv; /* second value is number of entries */
+
+ size_cpu_times = sizeof(int64_t) * CPUSTATES;
+ cpu_times = malloc(size_cpu_times);
+ if (!cpu_times)
+ error("cpu_sup: malloc error");
+
+ for (i = 0; i < ncpuonline; ++i) {
+ mib[2] = i;
+ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), cpu_times, &size_cpu_times, NULL, 0) == -1)
+ error("cpu_sup: sysctl error");
+
+ rv[ 0] = CU_CPU_ID; rv[ 1] = i;
+ rv[ 2] = CU_USER; rv[ 3] = (unsigned int)cpu_times[CP_USER];
+ rv[ 4] = CU_NICE_USER; rv[ 5] = (unsigned int)cpu_times[CP_NICE];
+ rv[ 6] = CU_KERNEL; rv[ 7] = (unsigned int)cpu_times[CP_SYS];
+ rv[ 8] = CU_IDLE; rv[ 9] = (unsigned int)cpu_times[CP_IDLE];
+ rv[10] = CU_HARD_IRQ; rv[11] = (unsigned int)cpu_times[CP_INTR];
+ rv += CU_OPENBSD_VALUES*2;
+ }
+ free((void*) cpu_times);
+
+ *result_sz = 2 + 2*CU_OPENBSD_VALUES * ncpuonline;
+}
+#endif
+
/* ---------------------------- *
* Generic functions *
diff --git a/lib/os_mon/doc/src/cpu_sup.xml b/lib/os_mon/doc/src/cpu_sup.xml
index e9dd930cf1..e79b3038b3 100644
--- a/lib/os_mon/doc/src/cpu_sup.xml
+++ b/lib/os_mon/doc/src/cpu_sup.xml
@@ -35,7 +35,7 @@
and CPU utilization. It is part of the OS_Mon application, see
<seeapp marker="os_mon_app">os_mon(6)</seeapp>. Available for Unix,
although CPU utilization values (<c>util/0,1</c>) are only
- available for Solaris, Linux and FreeBSD.</p>
+ available for Solaris, Linux, FreeBSD and OpenBSD.</p>
<p>The load values are proportional to how long time a runnable
Unix process has to spend in the run queue before it is scheduled.
Accordingly, higher values mean more system load. The returned
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index 1fac53d330..439c1e839a 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -31,6 +31,23 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.8.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Avoid error report from failing <c>erlang:port_close</c>
+ at shutdown of <c>cpu_sup</c> and <c>memsup</c>. Bug
+ exists since OTP 25.3 (os_mon-2.8.1).</p>
+ <p>
+ Own Id: OTP-18559 Aux Id: ERIERL-942 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.8.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl
index be917021e7..a82dfd9961 100644
--- a/lib/os_mon/src/cpu_sup.erl
+++ b/lib/os_mon/src/cpu_sup.erl
@@ -163,6 +163,7 @@ handle_call({?util, D, PC}, {Client, _Tag},
when Flavor == sunos;
Flavor == linux;
Flavor == freebsd;
+ Flavor == openbsd;
Flavor == darwin ->
case measurement_server_call(State#state.server, {?util, D, PC, Client}) of
{error, Reason} ->
@@ -613,8 +614,8 @@ port_server_loop(Port, Timeout) ->
% Close port and this server
{Pid, ?quit} ->
- port_command(Port, ?quit),
- port_close(Port),
+ Port ! {self(), {command, ?quit}},
+ Port ! {self(), close},
Pid ! {self(), {data, quit}},
ok;
diff --git a/lib/os_mon/src/memsup.erl b/lib/os_mon/src/memsup.erl
index 1c93bfbae4..c467adc2e5 100644
--- a/lib/os_mon/src/memsup.erl
+++ b/lib/os_mon/src/memsup.erl
@@ -653,7 +653,7 @@ start_portprogram() ->
port_shutdown(Port) ->
Port ! {self(), {command, [?EXIT]}},
- port_close(Port).
+ Port ! {self(), close}.
%% The connected process loops are a bit awkward (several different
%% functions doing almost the same thing) as
diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl
index e719963ea9..f3494da860 100644
--- a/lib/os_mon/test/cpu_sup_SUITE.erl
+++ b/lib/os_mon/test/cpu_sup_SUITE.erl
@@ -63,6 +63,8 @@ all() ->
[load_api, util_api, util_values, port, unavailable];
{unix, freebsd} ->
[load_api, util_api, util_values, port, unavailable];
+ {unix, openbsd} ->
+ [load_api, util_api, util_values, port, unavailable];
{unix, darwin} ->
[load_api, util_api, util_values, port, unavailable];
{unix, netbsd} -> [unavailable];
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index 9e64a83612..d6878e6773 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.8.1
+OS_MON_VSN = 2.8.2
diff --git a/lib/reltool/doc/src/reltool_intro.xml b/lib/reltool/doc/src/reltool_intro.xml
index 6e9aa4b92d..695d2c21e5 100644
--- a/lib/reltool/doc/src/reltool_intro.xml
+++ b/lib/reltool/doc/src/reltool_intro.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2016</year>
+ <year>2023</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/runtime_tools/doc/src/part.xml b/lib/runtime_tools/doc/src/part.xml
index 08ee495a1b..9b92ab0bfd 100644
--- a/lib/runtime_tools/doc/src/part.xml
+++ b/lib/runtime_tools/doc/src/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2012</year><year>2016</year>
+ <year>2012</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl
index ca1ce7948c..8cb65000ec 100644
--- a/lib/runtime_tools/src/dbg.erl
+++ b/lib/runtime_tools/src/dbg.erl
@@ -41,6 +41,7 @@
match_front/2, match_rear/2,
match_0_9/1]).
+-deprecated([{stop_clear,0, "use dbg:stop/0 instead"}]).
%%% Shell callable utility
fun2ms(ShellFun) when is_function(ShellFun) ->
@@ -582,14 +583,14 @@ c(M, F, A, Flags) ->
Mref = erlang:monitor(process, Pid),
receive
{'DOWN', Mref, _, _, Reason} ->
- stop_clear(),
+ stop(),
{error, Reason};
{Pid, Res} ->
erlang:demonitor(Mref, [flush]),
%% 'sleep' prevents the tracer (recv_all_traces) from
%% receiving garbage {'EXIT',...} when dbg i stopped.
timer:sleep(1),
- stop_clear(),
+ stop(),
Res
end
end.
@@ -1953,6 +1954,6 @@ h(stop) ->
h(stop_clear) ->
help_display(
["stop_clear() -> ok",
- " - Stops the dbg server and the tracing of all processes,",
+ " - Deprecated. Stops the dbg server and the tracing of all processes,",
" and clears all trace patterns."]).
diff --git a/lib/runtime_tools/src/erts_alloc_config.erl b/lib/runtime_tools/src/erts_alloc_config.erl
index c10c506b80..e6ac47fa8f 100644
--- a/lib/runtime_tools/src/erts_alloc_config.erl
+++ b/lib/runtime_tools/src/erts_alloc_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl
index ce4e122107..7983e62389 100644
--- a/lib/runtime_tools/test/dbg_SUITE.erl
+++ b/lib/runtime_tools/test/dbg_SUITE.erl
@@ -50,7 +50,7 @@ init_per_suite(Config) ->
Config.
end_per_suite(_Config) ->
- dbg:stop_clear(),
+ dbg:stop(),
ok.
%% Rudimentary interface test
@@ -89,7 +89,7 @@ big(Config) when is_list(Config) ->
ok=file:set_cwd(OldCurDir)
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -120,7 +120,7 @@ tiny(Config) when is_list(Config) ->
failure
end
after
- dbg:stop_clear(),
+ dbg:stop(),
ok = file:set_cwd(OldCurDir)
end,
ok.
@@ -136,7 +136,7 @@ simple(Config) when is_list(Config) ->
S = self(),
[{trace,S,call,{dbg,ltp,[]}}] = flush()
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -152,7 +152,7 @@ message(Config) when is_list(Config) ->
ok = dbg:ltp(),
ok = dbg:ln()
after
- dbg:stop_clear()
+ dbg:stop()
end,
S = self(),
[{trace,S,call,{dbg,ltp,[]},S},
@@ -235,7 +235,7 @@ send(Config) when is_list(Config) ->
ok
after
- dbg:stop_clear(),
+ dbg:stop(),
peer:stop(Peer)
end.
@@ -347,7 +347,7 @@ recv(Config) when is_list(Config) ->
ok
after
- dbg:stop_clear(),
+ dbg:stop(),
peer:stop(Peer)
end.
@@ -412,7 +412,7 @@ distributed(Config) when is_list(Config) ->
%%
stop()
after
- dbg:stop_clear(),
+ dbg:stop(),
peer:stop(Peer)
end,
ok.
@@ -463,7 +463,7 @@ local_trace(Config) when is_list(Config) ->
{dbg_SUITE,not_exported,1},
{error,badarith}}] = flush()
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -488,7 +488,7 @@ port(Config) when is_list(Config) ->
{trace,Port,getting_linked,S},
{trace,Port,closed,normal}] = flush()
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -514,7 +514,7 @@ saved_patterns(Config) when is_list(Config) ->
S = self(),
[{trace,S,call,{dbg,ltp,[]},blahonga}] = flush()
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -546,7 +546,7 @@ ip_port(Config) when is_list(Config) ->
[{trace,S,call,{dbg,ltp,[]},S},
{trace,S,call,{dbg,ln,[]},hej}] = flush()
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -562,7 +562,7 @@ ip_port_busy(Config) when is_list(Config) ->
io:format("Error reason = ~p~n", [Reason]),
true = port_close(Port)
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -587,7 +587,7 @@ file_port(Config) when is_list(Config) ->
{trace,S,call,{dbg,ln,[]},hej},
end_of_trace] = flush()
after
- dbg:stop_clear(),
+ dbg:stop(),
file:delete(FName)
end,
ok.
@@ -616,7 +616,7 @@ file_port2(Config) when is_list(Config) ->
stop(),
[] = flush()
after
- dbg:stop_clear(),
+ dbg:stop(),
file:delete(FName)
end,
ok.
@@ -641,7 +641,7 @@ file_tracer(Config) when is_list(Config) ->
<<"dbg:ln()",_/binary>> = string:find(LN, "dbg:ln() (hej)"),
stop()
after
- dbg:stop_clear(),
+ dbg:stop(),
file:delete(FName)
end,
ok.
@@ -709,7 +709,7 @@ wrap_port(Config) when is_list(Config) ->
%%
lists:map(fun(F) -> file:delete(F) end, Files)
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -781,7 +781,7 @@ wrap_port_time(Config) when is_list(Config) ->
end_of_trace] = flush(),
lists:map(fun(F) -> file:delete(F) end, Files)
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -807,7 +807,7 @@ with_seq_trace(Config) when is_list(Config) ->
{seq_trace,0,{send,_,Server,S,{dbg,{ok,Tracer}}}}] =
flush()
after
- dbg:stop_clear()
+ dbg:stop()
end,
ok.
@@ -818,7 +818,7 @@ dead_suspend(Config) when is_list(Config) ->
try
survived = run_dead_suspend()
after
- dbg:stop_clear()
+ dbg:stop()
end.
run_dead_suspend() ->
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index cb4eb5985f..01cff8fa4b 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -34,7 +34,23 @@
</header>
- <section><title>SNMP 5.13.4</title>
+ <section><title>SNMP 5.13.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Attempts to minimize the number of the error reports
+ during a failed agent init.</p>
+ <p>
+ Own Id: OTP-18422 Aux Id: ERIERL-873 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.13.4</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/snmp/doc/src/snmp_intro.xml b/lib/snmp/doc/src/snmp_intro.xml
index b8b3d4c984..819a34fc9c 100644
--- a/lib/snmp/doc/src/snmp_intro.xml
+++ b/lib/snmp/doc/src/snmp_intro.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 4c11344234..13c7e9790e 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 5.13.4
+SNMP_VSN = 5.13.5
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
index 85b3399295..7ef69630fe 100644
--- a/lib/ssh/src/ssh_dbg.erl
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -113,7 +113,7 @@ start(IoFmtFun) when is_function(IoFmtFun,2) ; is_function(IoFmtFun,3) ->
stop() ->
try
- dbg:stop_clear(),
+ dbg:stop(),
gen_server:stop(?SERVER)
catch
_:_ -> ok
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index a36ac8d78d..911055d742 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,30 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 10.9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, ssl:connection_information/2 returns
+ correct keylog data after TLS1.3 key update.</p>
+ <p>
+ Own Id: OTP-18489</p>
+ </item>
+ <item>
+ <p>
+ Client signature algorithm list input order is now
+ honored again , it was accidently reversed by a previous
+ fix.</p>
+ <p>
+ Own Id: OTP-18550</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 10.9</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -444,6 +468,23 @@
</section>
+<section><title>SSL 10.7.3.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Client signature algorithm list input order is now
+ honored again , it was accidently reversed by a previous
+ fix.</p>
+ <p>
+ Own Id: OTP-18550</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 10.7.3.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 3574ae91ac..700709ed7a 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -819,7 +819,7 @@ marker="public_key:public_key#pkix_path_validation/3">public_key:pkix_path_valid
<desc>
<code>
fun(Chain::[public_key:der_encoded()]) ->
- {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca}
+ {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca.
</code>
<p>Claim an intermediate CA in the chain as trusted. TLS then
performs <seemfa
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index a37a72efdc..899e7d3305 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -479,10 +479,7 @@ wait_cert_verify(info, Event, State) ->
wait_cert_verify(state_timeout, Event, State) ->
handle_state_timeout(Event, ?FUNCTION_NAME, State);
wait_cert_verify(Type, Event, State) ->
- try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
- catch throw:#alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
- end.
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(), term(), #state{}) ->
@@ -506,7 +503,7 @@ cipher(internal = Type, #finished{} = Event, #state{connection_states = Connecti
cipher(state_timeout, Event, State) ->
handle_state_timeout(Event, ?FUNCTION_NAME, State);
cipher(Type, Event, State) ->
- gen_handshake(?FUNCTION_NAME, Type, Event, State).
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
-spec connection(gen_statem:event_type(),
@@ -761,6 +758,8 @@ alert_or_reset_connection(Alert, StateName, #state{connection_states = Cs} = Sta
{next_state, connection, NewState}
end.
+gen_handshake(_, {call, _From}, {application_data, _Data}, _State) ->
+ {keep_state_and_data, [postpone]};
gen_handshake(StateName, Type, Event, State) ->
try tls_dtls_connection:StateName(Type, Event, State)
catch
diff --git a/lib/ssl/src/dtls_handshake.hrl b/lib/ssl/src/dtls_handshake.hrl
index 1abda1eee4..ea7a1d72a0 100644
--- a/lib/ssl/src/dtls_handshake.hrl
+++ b/lib/ssl/src/dtls_handshake.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/dtls_v1.erl b/lib/ssl/src/dtls_v1.erl
index 9bcb3b6184..851de78963 100644
--- a/lib/ssl/src/dtls_v1.erl
+++ b/lib/ssl/src/dtls_v1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 4e766ac1f5..c96173e98b 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -264,7 +264,7 @@
secp160r1 |
secp160r2.
--type group() :: secp256r1 | secp384r1 | secp521r1 | ffdhe2048 |
+-type group() :: x25519 | x448 | secp256r1 | secp384r1 | secp521r1 | ffdhe2048 |
ffdhe3072 | ffdhe4096 | ffdhe6144 | ffdhe8192. % exported
-type srp_param_type() :: srp_1024 |
@@ -1703,18 +1703,22 @@ validate_versions(dtls, Vsns0) ->
opt_verification(UserOpts, Opts0, #{role := Role} = Env) ->
{Verify, Opts1} =
case get_opt_of(verify, [verify_none, verify_peer], default_verify(Role), UserOpts, Opts0) of
+ {old, Val} ->
+ {Val, Opts0};
{_, verify_none} ->
{verify_none, Opts0#{verify => verify_none, verify_fun => {none_verify_fun(), []}}};
{_, verify_peer} ->
%% If 'verify' is changed from verify_none to verify_peer, (via update_options/3)
%% the 'verify_fun' must also be changed to undefined.
%% i.e remove verify_none fun
- {verify_peer, Opts0#{verify => verify_peer, verify_fun => undefined}}
+ Temp = Opts0#{verify => verify_peer, verify_fun => undefined},
+ {verify_peer, maps:remove(fail_if_no_peer_cert, Temp)}
end,
Opts2 = opt_cacerts(UserOpts, Opts1, Env),
{_, PartialChain} = get_opt_fun(partial_chain, 1, fun(_) -> unknown_ca end, UserOpts, Opts2),
- {_, FailNoPeerCert} = get_opt_bool(fail_if_no_peer_cert, false, UserOpts, Opts2),
+ DefFailNoPeer = Role =:= server andalso Verify =:= verify_peer,
+ {_, FailNoPeerCert} = get_opt_bool(fail_if_no_peer_cert, DefFailNoPeer, UserOpts, Opts2),
assert_server_only(Role, FailNoPeerCert, fail_if_no_peer_cert),
option_incompatible(FailNoPeerCert andalso Verify =:= verify_none,
[{verify, verify_none}, {fail_if_no_peer_cert, true}]),
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 1d217bde73..8d982f7fa2 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -632,7 +632,7 @@ signature_scheme(SignAlgo) when is_integer(SignAlgo) ->
signature_scheme(_) -> unassigned.
signature_schemes_1_2(SigAlgs) ->
- lists:foldl(fun(Alg, Acc) when is_atom(Alg) ->
+ lists:reverse(lists:foldl(fun(Alg, Acc) when is_atom(Alg) ->
case scheme_to_components(Alg) of
{Hash, Sign = rsa_pss_pss,_} ->
[{Hash, Sign} | Acc];
@@ -643,7 +643,7 @@ signature_schemes_1_2(SigAlgs) ->
end;
(Alg, Acc) ->
[Alg| Acc]
- end, [], SigAlgs).
+ end, [], SigAlgs)).
%% TODO: reserved code points?
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 684f2c8530..f98be277bf 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/ssl_logger.erl b/lib/ssl/src/ssl_logger.erl
index 047fa3a39c..e9131b28a5 100644
--- a/lib/ssl/src/ssl_logger.erl
+++ b/lib/ssl/src/ssl_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 18fb016b53..9daee92c5b 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index 8eee2d3d3f..c58a931ab5 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index 0b094580b0..721a9ef4d5 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 92205d22fd..01f85624bf 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/tls_record.hrl b/lib/ssl/src/tls_record.hrl
index c95c25418c..d2e6ad262f 100644
--- a/lib/ssl/src/tls_record.hrl
+++ b/lib/ssl/src/tls_record.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/tls_record_1_3.erl b/lib/ssl/src/tls_record_1_3.erl
index f636734377..abd67774ce 100644
--- a/lib/ssl/src/tls_record_1_3.erl
+++ b/lib/ssl/src/tls_record_1_3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/tls_record_1_3.hrl b/lib/ssl/src/tls_record_1_3.hrl
index cbe898317e..c2624e8fde 100644
--- a/lib/ssl/src/tls_record_1_3.hrl
+++ b/lib/ssl/src/tls_record_1_3.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/tls_socket.erl b/lib/ssl/src/tls_socket.erl
index 6974ed0f64..fd919f7356 100644
--- a/lib/ssl/src/tls_socket.erl
+++ b/lib/ssl/src/tls_socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/openssl_alpn_SUITE.erl b/lib/ssl/test/openssl_alpn_SUITE.erl
index 1bf8cbf5fd..1d0bc82c4e 100644
--- a/lib/ssl/test/openssl_alpn_SUITE.erl
+++ b/lib/ssl/test/openssl_alpn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -194,7 +194,7 @@ erlang_client_alpn_openssl_server_alpn(Config) when is_list(Config) ->
erlang_server_alpn_openssl_client_alpn(Config) when is_list(Config) ->
ClientOpts = proplists:get_value(client_rsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
Protocol = <<"spdy/2">>,
Server = ssl_test_lib:start_server(erlang, [{from, self()}],
[{server_opts, [{alpn_preferred_protocols,
diff --git a/lib/ssl/test/openssl_renegotiate_SUITE.erl b/lib/ssl/test/openssl_renegotiate_SUITE.erl
index 01b5a7a8a9..5102730396 100644
--- a/lib/ssl/test/openssl_renegotiate_SUITE.erl
+++ b/lib/ssl/test/openssl_renegotiate_SUITE.erl
@@ -230,7 +230,7 @@ erlang_server_openssl_client_nowrap_seqnum() ->
erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
{_, ServerNode, _Hostname} = ssl_test_lib:run_where(Config),
diff --git a/lib/ssl/test/openssl_server_cert_SUITE.erl b/lib/ssl/test/openssl_server_cert_SUITE.erl
index 03653ab0d6..057d80b6f3 100644
--- a/lib/ssl/test/openssl_server_cert_SUITE.erl
+++ b/lib/ssl/test/openssl_server_cert_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/property_test/ssl_eqc_handshake.erl b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
index 230a676579..8f5aaedd1c 100644
--- a/lib/ssl/test/property_test/ssl_eqc_handshake.erl
+++ b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2023. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index 86ca9b8ec9..379cc6371b 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/ssl_api_SUITE.erl b/lib/ssl/test/ssl_api_SUITE.erl
index a3bb2f6bdc..215097bd4d 100644
--- a/lib/ssl/test/ssl_api_SUITE.erl
+++ b/lib/ssl/test/ssl_api_SUITE.erl
@@ -2699,18 +2699,18 @@ options_verify(Config) -> %% fail_if_no_peer_cert, verify, verify_fun, partial_
?OK(#{fail_if_no_peer_cert := true, verify := verify_peer, verify_fun := undefined, partial_chain := _},
[{fail_if_no_peer_cert, true}, {verify, verify_peer}, {cacerts, [Cert]}],
server),
- ?OK(#{fail_if_no_peer_cert := false, verify := verify_peer, verify_fun := undefined, partial_chain := _},
- [{verify, verify_peer}, {cacerts, [Cert]}], server),
+ ?OK(#{fail_if_no_peer_cert := true, verify := verify_peer, verify_fun := undefined, partial_chain := _},
+ [{verify, verify_peer}, {cacerts, [Cert]}], server),
NewF3 = fun(_,_,_) -> ok end,
NewF4 = fun(_,_,_,_) -> ok end,
?OK(#{}, [], client, [fail_if_no_peer_cert]),
?OK(#{verify := verify_none, verify_fun := {NewF3, foo}, partial_chain := _},
[{verify_fun, {NewF3, foo}}], client),
- ?OK(#{fail_if_no_peer_cert := false, verify := verify_peer, verify_fun := {NewF3, foo}, partial_chain := _},
+ ?OK(#{fail_if_no_peer_cert := true, verify := verify_peer, verify_fun := {NewF3, foo}, partial_chain := _},
[{verify_fun, {NewF3, foo}}, {verify, verify_peer}, {cacerts, [Cert]}],
server),
- ?OK(#{fail_if_no_peer_cert := false, verify := verify_peer, verify_fun := {NewF4, foo}, partial_chain := _},
+ ?OK(#{fail_if_no_peer_cert := true, verify := verify_peer, verify_fun := {NewF4, foo}, partial_chain := _},
[{verify_fun, {NewF4, foo}}, {verify, verify_peer}, {cacerts, [Cert]}],
server),
diff --git a/lib/ssl/test/ssl_cipher_SUITE.erl b/lib/ssl/test/ssl_cipher_SUITE.erl
index b9e0fda0c6..687bbd6f58 100644
--- a/lib/ssl/test/ssl_cipher_SUITE.erl
+++ b/lib/ssl/test/ssl_cipher_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,8 @@
aes_decipher_good/1,
aes_decipher_fail/0,
aes_decipher_fail/1,
- padding_test/1
+ padding_test/1,
+ sign_algorithms/1
]).
@@ -50,7 +51,7 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [aes_decipher_good, aes_decipher_fail, padding_test].
+ [aes_decipher_good, aes_decipher_fail, padding_test, sign_algorithms].
groups() ->
[].
@@ -120,6 +121,10 @@ padding_test(Config) when is_list(Config) ->
pad_test(HashSz, CipherState, ?TLS_1_1),
pad_test(HashSz, CipherState, ?TLS_1_2).
+%%--------------------------------------------------------------------
+sign_algorithms(Config) when is_list(Config) ->
+ [{sha256,rsa_pss_pss},{rsa,sha256}] = ssl_cipher:signature_schemes_1_2([rsa_pss_pss_sha256, {rsa, sha256}]).
+
%%--------------------------------------------------------------------
% Internal functions --------------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_dist_test_lib.erl b/lib/ssl/test/ssl_dist_test_lib.erl
index 78f99477a8..3df721f2d7 100644
--- a/lib/ssl/test/ssl_dist_test_lib.erl
+++ b/lib/ssl/test/ssl_dist_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/ssl_mfl_SUITE.erl b/lib/ssl/test/ssl_mfl_SUITE.erl
index 128ffaf725..0cff561938 100644
--- a/lib/ssl/test/ssl_mfl_SUITE.erl
+++ b/lib/ssl/test/ssl_mfl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/ssl_reject_SUITE.erl b/lib/ssl/test/ssl_reject_SUITE.erl
index 9f2c859055..cc24ffbcfe 100644
--- a/lib/ssl/test/ssl_reject_SUITE.erl
+++ b/lib/ssl/test/ssl_reject_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2021-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/ssl_renegotiate_SUITE.erl b/lib/ssl/test/ssl_renegotiate_SUITE.erl
index 49ce1ba6a7..2a58d5ee5b 100644
--- a/lib/ssl/test/ssl_renegotiate_SUITE.erl
+++ b/lib/ssl/test/ssl_renegotiate_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/ssl_session_SUITE.erl b/lib/ssl/test/ssl_session_SUITE.erl
index 3b36db70f5..b94932bfc6 100644
--- a/lib/ssl/test/ssl_session_SUITE.erl
+++ b/lib/ssl/test/ssl_session_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -464,8 +464,11 @@ no_reuses_session_server_restart_new_cert() ->
no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_der_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_der_verify_opts, Config),
- RSA1024ServerOpts = ssl_test_lib:ssl_options(server_rsa_1024_der_opts, Config),
- RSA1024ClientOpts = ssl_test_lib:ssl_options(client_rsa_1024_der_opts, Config),
+ #{client_config := NewCOpts,
+ server_config := NewSOpts} = ssl_test_lib:make_cert_chains_der(rsa,
+ [[{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ [{key, ssl_test_lib:hardcode_rsa_key(5)}],
+ [{key, ssl_test_lib:hardcode_rsa_key(6)}]]),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -490,12 +493,12 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
Server1 = ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
{from, self()},
{mfa, {ssl_test_lib, session_info_result, []}},
- {options, [{reuseaddr, true} | RSA1024ServerOpts]}]),
+ {options, [{reuseaddr, true} | NewSOpts]}]),
Client1 = ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
{mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, RSA1024ClientOpts}]),
+ {from, self()}, {options, NewCOpts}]),
Info1 = receive {Server1, Info10} -> Info10 end,
receive
@@ -517,7 +520,12 @@ no_reuses_session_server_restart_new_cert_file() ->
no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- RSA1024ServerOpts = ssl_test_lib:ssl_options(server_rsa_1024_verify_opts, Config),
+ #{client_config := NewCOpts,
+ server_config := NewSOpts} = ssl_test_lib:make_cert_chains_pem(rsa,
+ [[{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ [{key, ssl_test_lib:hardcode_rsa_key(5)}],
+ [{key, ssl_test_lib:hardcode_rsa_key(6)}]],
+ Config, "ssl_session_new_rsa"),
PrivDir = proplists:get_value(priv_dir, Config),
NewServerOpts0 = ssl_test_lib:new_config(PrivDir, ServerOpts),
@@ -548,7 +556,7 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
ssl:clear_pem_cache(),
- NewServerOpts1 = ssl_test_lib:new_config(PrivDir, RSA1024ServerOpts),
+ NewServerOpts1 = ssl_test_lib:new_config(PrivDir, NewSOpts),
Server1 =
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
@@ -559,7 +567,7 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
{mfa, {ssl_test_lib, session_info_result, []}},
- {from, self()}, {options, ClientOpts}]),
+ {from, self()}, {options, NewCOpts}]),
receive
{Client1, SessionInfo} ->
ct:fail(session_reused_when_server_has_new_cert);
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 01235a1d74..64ee3c9d0d 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -973,15 +973,19 @@ openssl_server_loop(Pid, SslPort, Args) ->
start_openssl_client(Args0, Config) ->
{ClientNode, _, Hostname} = run_where(Config),
- ClientOpts = get_client_opts(Config),
+
+ %% io:format("~p:~p: ~p~n",[?MODULE, ?LINE, Args0]),
+ %% io:format("~p:~p: ~p~n",[?MODULE, ?LINE, Config]),
+
+ ClientOpts0 = get_client_opts(Config),
+ ClientOpts = proplists:get_value(options, Args0, []) ++ ClientOpts0,
DefaultVersions = default_tls_version(ClientOpts),
[Version | _] = proplists:get_value(versions, ClientOpts, DefaultVersions),
Node = proplists:get_value(node, Args0, ClientNode),
- Args = [{from, self()},
- {host, Hostname},
- {options, ClientOpts} | Args0],
+ Args = [{from, self()}, {host, Hostname} | ClientOpts ++ Args0],
- Result = spawn_link(Node, ?MODULE, init_openssl_client, [[{version, Version} | lists:delete(return_port, Args)]]),
+ Result = spawn_link(Node, ?MODULE, init_openssl_client,
+ [[{version, Version} | lists:delete(return_port, Args)]]),
receive
{connected, OpenSSLPort} ->
case lists:member(return_port, Args) of
@@ -1636,9 +1640,7 @@ make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config, Curve) -
[{server_config, ServerConf},
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
- {[{verify, verify_peer} | ClientConf],
- [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
- }.
+ {ClientConf, [{reuseaddr, true} | ServerConf]}.
default_cert_chain_conf() ->
%% Use only default options
@@ -1654,8 +1656,8 @@ make_rsa_pss_pem(Alg, _UserConf, Config, Suffix) ->
Conf = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
CConf = proplists:get_value(client_config, Conf),
SConf = proplists:get_value(server_config, Conf),
- #{server_config => [{verify, verify_peer} | SConf],
- client_config => [{verify, verify_peer} | CConf]}.
+ #{server_config => SConf,
+ client_config => CConf}.
make_rsa_sni_configs() ->
Sha = appropriate_sha(crypto:supports()),
@@ -2032,7 +2034,7 @@ make_rsa_ecdsa_cert(Config, Curve) ->
[{server_rsa_ecdsa_opts, [{reuseaddr, true} | ServerConf]},
{server_rsa_ecdsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
{verify, verify_peer} | ServerConf]},
- {client_rsa_ecdsa_opts, [{verify, cerify_none} | ClientConf]} | Config];
+ {client_rsa_ecdsa_opts, [{verify, verify_none} | ClientConf]} | Config];
_ ->
Config
end.
@@ -2449,7 +2451,7 @@ start_server(erlang, _, ServerOpts, Config) ->
{mfa, {ssl_test_lib,
check_key_exchange_send_active,
[KeyEx]}},
- {options, [{verify, verify_peer} | ServerOpts]}]),
+ {options, ServerOpts}]),
{Server, inet_port(Server)}.
sig_algs(undefined) ->
diff --git a/lib/ssl/test/tls_1_3_record_SUITE.erl b/lib/ssl/test/tls_1_3_record_SUITE.erl
index b6c0f8df59..c08bd90a02 100644
--- a/lib/ssl/test/tls_1_3_record_SUITE.erl
+++ b/lib/ssl/test/tls_1_3_record_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/tls_1_3_version_SUITE.erl b/lib/ssl/test/tls_1_3_version_SUITE.erl
index 58aae7d1ee..b5aa0d3cad 100644
--- a/lib/ssl/test/tls_1_3_version_SUITE.erl
+++ b/lib/ssl/test/tls_1_3_version_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/tls_server_session_ticket_SUITE.erl b/lib/ssl/test/tls_server_session_ticket_SUITE.erl
index 325d2d44f2..3f5b0f71b2 100644
--- a/lib/ssl/test/tls_server_session_ticket_SUITE.erl
+++ b/lib/ssl/test/tls_server_session_ticket_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 7b821e2bc8..db6de41e50 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 10.9
+SSL_VSN = 10.9.1
diff --git a/lib/stdlib/Makefile b/lib/stdlib/Makefile
index f1db3c77e3..f1a72cd6b9 100644
--- a/lib/stdlib/Makefile
+++ b/lib/stdlib/Makefile
@@ -39,6 +39,7 @@ include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=compiler crypto
TEST_NEEDS_RELEASE=true
+NO_TEST_TARGET:=1 # Avoid warning about ignoring old recipe for target 'test'
include $(ERL_TOP)/make/app_targets.mk
# Enable feature maybe_expr in runtime when running tests.
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 5b1bc2b483..d13fa47064 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -33,6 +33,7 @@ APPLICATION=stdlib
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = \
+ argparse.xml \
array.xml \
base64.xml \
beam_lib.xml \
diff --git a/lib/stdlib/doc/src/argparse.xml b/lib/stdlib/doc/src/argparse.xml
new file mode 100644
index 0000000000..20e1f3a721
--- /dev/null
+++ b/lib/stdlib/doc/src/argparse.xml
@@ -0,0 +1,739 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<!-- %ExternalCopyright% -->
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2020</year><year>2023</year>
+ <holder>Maxim Fedorov</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>argparse</title>
+ <prepared>maximfca@gmail.com</prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>argparse.xml</file>
+ </header>
+ <module since="OTP 26.0">argparse</module>
+ <modulesummary>Command line arguments parser.</modulesummary>
+ <description>
+
+ <p>This module implements command line parser. Parser operates with
+ <em>commands</em> and <em>arguments</em> represented as a tree. Commands
+ are branches, and arguments are leaves of the tree. Parser always starts with the
+ root command, named after <c>progname</c> (the name of the program which started Erlang).
+ </p>
+
+ <p>
+ A <seetype marker="#command"><c>command specification</c></seetype> may contain handler
+ definition for each command, and a number argument specifications. When parser is
+ successful, <c>argparse</c> calls the matching handler, passing arguments extracted
+ from the command line. Arguments can be positional (occupying specific position in
+ the command line), and optional, residing anywhere but prefixed with a specified
+ character.
+ </p>
+
+ <p>
+ <c>argparse</c> automatically generates help and usage messages. It will also issue
+ errors when users give the program invalid arguments.
+ </p>
+
+ </description>
+
+ <section>
+ <title>Quick start</title>
+
+ <p><c>argparse</c> is designed to work with <seecom marker="erts:escript"><c>escript</c></seecom>.
+ The example below is a fully functioning Erlang program accepting two command line
+ arguments and printing their product.</p>
+
+ <code>
+#!/usr/bin/env escript
+
+main(Args) ->
+ argparse:run(Args, cli(), #{progname => mul}).
+
+cli() ->
+ #{
+ arguments => [
+ #{name => left, type => integer},
+ #{name => right, type => integer}
+ ],
+ handler =>
+ fun (#{left := Left, right := Right}) ->
+ io:format("~b~n", [Left * Right])
+ end
+ }.
+ </code>
+
+ <p>Running this script with no arguments results in an error, accompanied
+ by the usage information.</p>
+
+ <p>
+ The <c>cli</c> function defines a single command with embedded handler
+ accepting a map. Keys of the map are argument names as defined by
+ the <c>argument</c> field of the command, <c>left</c> and <c>right</c>
+ in the example. Values are taken from the command line, and converted
+ into integers, as requested by the type specification. Both arguments
+ in the example above are required (and therefore defined as positional).
+ </p>
+ </section>
+
+ <section>
+ <title>Command hierarchy</title>
+
+ <p>A command may contain nested commands, forming a hierarchy. Arguments
+ defined at the upper level command are automatically added to all nested
+ commands. Nested commands example (assuming <c>progname</c> is <c>nested</c>):
+ </p>
+
+ <code>
+cli() ->
+ #{
+ %% top level argument applicable to all commands
+ arguments => [#{name => top}],
+ commands => #{
+ "first" => #{
+ %% argument applicable to "first" command and
+ %% all commands nested into "first"
+ arguments => [#{name => mid}],
+ commands => #{
+ "second" => #{
+ %% argument only applicable for "second" command
+ arguments => [#{name => bottom}],
+ handler => fun (A) -> io:format("~p~n", [A]) end
+ }
+ }
+ }
+ }
+ }.
+ </code>
+
+ <p>In the example above, a 3-level hierarchy is defined. First is the script
+ itself (<c>nested</c>), accepting the only argument <c>top</c>. Since it
+ has no associated handler, <seemfa marker="#run/3">run/3</seemfa> will
+ not accept user input omitting nested command selection. For this example,
+ user has to supply 5 arguments in the command line, two being command
+ names, and another 3 - required positional arguments:</p>
+
+ <code>
+./nested.erl one first second two three
+#{top => "one",mid => "two",bottom => "three"}
+ </code>
+
+ <p>Commands have preference over positional argument values. In the example
+ above, commands and positional arguments are interleaving, and <c>argparse</c>
+ matches command name first.</p>
+
+ </section>
+
+ <section>
+ <title>Arguments</title>
+ <p><c>argparse</c> supports positional and optional arguments. Optional arguments,
+ or options for short, must be prefixed with a special character (<c>-</c> is the default
+ on all operating systems). Both options and positional arguments have 1 or more associated
+ values. See <seetype marker="#argument"><c>argument specification</c></seetype> to
+ find more details about supported combinations.</p>
+
+ <p>In the user input, short options may be concatenated with their values. Long
+ options support values separated by <c>=</c>. Consider this definition:</p>
+
+ <code>
+cli() ->
+ #{
+ arguments => [
+ #{name => long, long => "-long"},
+ #{name => short, short => $s}
+ ],
+ handler => fun (Args) -> io:format("~p~n", [Args]) end
+ }.
+ </code>
+
+ <p>Running <c>./args --long=VALUE</c> prints <c>#{long => "VALUE"}</c>, running
+ <c>./args -sVALUE</c> prints <c>#{short => "VALUE"}</c></p>
+
+ <p><c>argparse</c> supports boolean flags concatenation: it is possible to shorten
+ <c>-r -f -v</c> to <c>-rfv</c>.</p>
+
+ <p>Shortened option names are not supported: it is not possible to use <c>--my-argum</c>
+ instead of <c>--my-argument-name</c> even when such option can be unambiguously found.</p>
+ </section>
+
+ <datatypes>
+ <datatype>
+ <name name="arg_type"/>
+ <desc>
+ <p>Defines type conversion applied to the string retrieved from the user input.
+ If the conversion is successful, resulting value is validated using optional
+ <c>Choices</c>, or minimums and maximums (for integer and floating point values
+ only). Strings and binary values may be validated using regular expressions.
+ It's possible to define custom type conversion function, accepting a string
+ and returning Erlang term. If this function raises error with <c>badarg</c>
+ reason, argument is treated as invalid.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="argument_help"/>
+ <desc>
+ <p>User-defined help template to print in the command usage. First element of
+ a tuple must be a string. It is printed as a part of the usage header. Second
+ element of the tuple can be either a string printed as-is, a list
+ containing strings, <c>type</c> and <c>default</c> atoms, or a user-defined
+ function that must return a string.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="argument_name"/>
+ <desc>
+ <p>Argument name is used to populate argument map.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="argument"/>
+ <desc>
+ <p>Argument specification. Defines a single named argument that is returned
+ in the <seetype marker="#arg_map"><c>argument map</c></seetype>. The only
+ required field is <c>name</c>, all other fields have defaults.</p>
+ <p>If either of the <c>short</c> or <c>long</c> fields is specified, the
+ argument is treated as optional. Optional arguments do not have specific
+ order and may appear anywhere in the command line. Positional arguments
+ are ordered the same way as they appear in the arguments list of the command
+ specification.</p>
+ <p>By default, all positional arguments must be present in the command line.
+ The parser will return an error otherwise. Options, however, may be omitted,
+ in which case resulting argument map will either contain the default value,
+ or not have the key at all.</p>
+ <taglist>
+ <tag><c>name</c></tag>
+ <item>
+ <p>Sets the argument name in the parsed argument map. If <c>help</c> is not defined,
+ name is also used to generate the default usage message.
+ </p>
+ </item>
+ <tag><c>short</c></tag>
+ <item>
+ <p>Defines a short (single character) form of an optional argument.</p>
+ <code>
+%% Define a command accepting argument named myarg, with short form $a:
+1> Cmd = #{arguments => [#{name => myarg, short => $a}]}.
+%% Parse command line "-a str":
+2> {ok, ArgMap, _, _} = argparse:parse(["-a", "str"], Cmd), ArgMap.
+
+#{myarg => "str"}
+
+%% Option value can be concatenated with the switch: "-astr"
+3> {ok, ArgMap, _, _} = argparse:parse(["-astr"], Cmd), ArgMap.
+
+#{myarg => "str"}
+ </code>
+ <p>By default all options expect a single value following the option switch.
+ The only exception is an option of a boolean type.</p>
+ </item>
+ <tag><c>long</c></tag>
+ <item>
+ <p>Defines a long form of an optional argument.</p>
+ <code>
+1> Cmd = #{arguments => [#{name => myarg, long => "name"}]}.
+%% Parse command line "-name Erlang":
+2> {ok, ArgMap, _, _} = argparse:parse(["-name", "Erlang"], Cmd), ArgMap.
+
+#{myarg => "Erlang"}
+%% Or use "=" to separate the switch and the value:
+3> {ok, ArgMap, _, _} = argparse:parse(["-name=Erlang"], Cmd), ArgMap.
+
+#{myarg => "Erlang"}
+ </code>
+ <p>If neither <c>short</c> not <c>long</c> is defined, the
+ argument is treated as positional.</p>
+ </item>
+ <tag><c>required</c></tag>
+ <item>
+ <p>Forces the parser to expect the argument to be present in the
+ command line. By default, all positional argument are required,
+ and all options are not.</p>
+ </item>
+ <tag><c>default</c></tag>
+ <item>
+ <p>Specifies the default value to put in the parsed argument map
+ if the value is not supplied in the command line.</p>
+ <code>
+1> argparse:parse([], #{arguments => [#{name => myarg, short => $m}]}).
+
+{ok,#{}, ...
+2> argparse:parse([], #{arguments => [#{name => myarg, short => $m, default => "def"}]}).
+
+{ok,#{myarg => "def"}, ...
+ </code>
+ </item>
+ <tag><c>type</c></tag>
+ <item>
+ <p>Defines type conversion and validation routine. The default is <c>string</c>,
+ assuming no conversion.</p>
+ </item>
+ <tag><c>nargs</c></tag>
+ <item>
+ <p>Defines the number of following arguments to consume from the command line.
+ By default, the parser consumes the next argument and converts it into an
+ Erlang term according to the specified type.
+ </p>
+ <taglist>
+ <tag><c>pos_integer()</c></tag>
+ <item><p> Consume exactly this number of positional arguments, fail if there
+ is not enough. Value in the argument map contains a list of exactly this
+ length. Example, defining a positional argument expecting 3 integer values:</p>
+ <code>
+1> Cmd = #{arguments => [#{name => ints, type => integer, nargs => 3}]},
+argparse:parse(["1", "2", "3"], Cmd).
+
+{ok, #{ints => [1, 2, 3]}, ...
+ </code>
+ <p>Another example defining an option accepted as <c>-env</c> and
+ expecting two string arguments:</p>
+ <code>
+1> Cmd = #{arguments => [#{name => env, long => "env", nargs => 2}]},
+argparse:parse(["-env", "key", "value"], Cmd).
+
+{ok, #{env => ["key", "value"]}, ...
+ </code>
+ </item>
+ <tag><c>list</c></tag>
+ <item>
+ <p>Consume all following arguments until hitting the next option (starting
+ with an option prefix). May result in an empty list added to the arguments
+ map.</p>
+ <code>
+1> Cmd = #{arguments => [
+ #{name => nodes, long => "nodes", nargs => list},
+ #{name => verbose, short => $v, type => boolean}
+]},
+argparse:parse(["-nodes", "one", "two", "-v"], Cmd).
+
+{ok, #{nodes => ["one", "two"], verbose => true}, ...
+ </code>
+ </item>
+ <tag><c>nonempty_list</c></tag>
+ <item>
+ <p>Same as <c>list</c>, but expects at least one argument. Returns an error
+ if the following command line argument is an option switch (starting with the
+ prefix).</p>
+ </item>
+ <tag><c>'maybe'</c></tag>
+ <item>
+ <p>Consumes the next argument from the command line, if it does not start
+ with an option prefix. Otherwise, adds a default value to the arguments
+ map.</p>
+ <code>
+1> Cmd = #{arguments => [
+ #{name => level, short => $l, nargs => 'maybe', default => "error"},
+ #{name => verbose, short => $v, type => boolean}
+]},
+argparse:parse(["-l", "info", "-v"], Cmd).
+
+{ok,#{level => "info",verbose => true}, ...
+
+%% When "info" is omitted, argument maps receives the default "error"
+2> argparse:parse(["-l", "-v"], Cmd).
+
+{ok,#{level => "error",verbose => true}, ...
+ </code>
+ </item>
+ <tag><c>{'maybe', term()}</c></tag>
+ <item>
+ <p>Consumes the next argument from the command line, if it does not start
+ with an option prefix. Otherwise, adds a specified Erlang term to the
+ arguments map.</p>
+ </item>
+ <tag><c>all</c></tag>
+ <item>
+ <p>Fold all remaining command line arguments into a list, ignoring
+ any option prefixes or switches. Useful for proxying arguments
+ into another command line utility.</p>
+ <code>
+1> Cmd = #{arguments => [
+ #{name => verbose, short => $v, type => boolean},
+ #{name => raw, long => "-", nargs => all}
+]},
+argparse:parse(["-v", "--", "-kernel", "arg", "opt"], Cmd).
+
+{ok,#{raw => ["-kernel","arg","opt"],verbose => true}, ...
+ </code>
+ </item>
+ </taglist>
+ </item>
+ <tag><c>action</c></tag>
+ <item>
+ <p>Defines an action to take when the argument is found in the command line. The
+ default action is <c>store</c>.</p>
+ <taglist>
+ <tag><c>store</c></tag>
+ <item><p>
+ Store the value in the arguments map. Overwrites the value previously written.
+ </p>
+ <code>
+1> Cmd = #{arguments => [#{name => str, short => $s}]},
+argparse:parse(["-s", "one", "-s", "two"], Cmd).
+
+{ok, #{str => "two"}, ...
+ </code>
+ </item>
+ <tag><c>{store, term()}</c></tag>
+ <item><p>
+ Stores the specified term instead of reading the value from the command line.
+ </p>
+ <code>
+1> Cmd = #{arguments => [#{name => str, short => $s, action => {store, "two"}}]},
+argparse:parse(["-s"], Cmd).
+
+{ok, #{str => "two"}, ...
+ </code>
+ </item>
+ <tag><c>append</c></tag>
+ <item><p>
+ Appends the repeating occurrences of the argument instead of overwriting.
+ </p>
+ <code>
+1> Cmd = #{arguments => [#{name => node, short => $n, action => append}]},
+argparse:parse(["-n", "one", "-n", "two", "-n", "three"], Cmd).
+
+{ok, #{node => ["one", "two", "three"]}, ...
+
+%% Always produces a list - even if there is one occurrence
+2> argparse:parse(["-n", "one"], Cmd).
+
+{ok, #{node => ["one"]}, ...
+ </code>
+ </item>
+ <tag><c>{append, term()}</c></tag>
+ <item><p>
+ Same as <c>append</c>, but instead of consuming the argument from the
+ command line, appends a provided <c>term()</c>.
+ </p></item>
+ <tag><c>count</c></tag>
+ <item><p>
+ Puts a counter as a value in the arguments map. Useful for implementing
+ verbosity option:
+ </p>
+ <code>
+1> Cmd = #{arguments => [#{name => verbose, short => $v, action => count}]},
+argparse:parse(["-v"], Cmd).
+
+{ok, #{verbose => 1}, ...
+
+2> argparse:parse(["-vvvv"], Cmd).
+
+{ok, #{verbose => 4}, ...
+ </code>
+ </item>
+ <tag><c>extend</c></tag>
+ <item><p>
+ Works as <c>append</c>, but flattens the resulting list.
+ Valid only for <c>nargs</c> set to <c>list</c>, <c>nonempty_list</c>,
+ <c>all</c> or <c>pos_integer()</c>.
+ </p>
+ <code>
+1> Cmd = #{arguments => [#{name => duet, short => $d, nargs => 2, action => extend}]},
+argparse:parse(["-d", "a", "b", "-d", "c", "d"], Cmd).
+
+{ok, #{duet => ["a", "b", "c", "d"]}, ...
+
+%% 'append' would result in {ok, #{duet => [["a", "b"],["c", "d"]]},
+ </code>
+ </item>
+ </taglist>
+ </item>
+ <tag><c>help</c></tag>
+ <item>
+ <p>Specifies help/usage text for the argument. <c>argparse</c> provides automatic
+ generation based on the argument name, type and default value, but for better
+ usability it is recommended to have a proper description. Setting this field
+ to <c>hidden</c> suppresses usage output for this argument.</p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="arg_map"/>
+ <desc>
+ <p>Arguments map is the map of argument names to the values extracted from the
+ command line. It is passed to the matching command handler.
+ If an argument is omitted, but has the default value is specified,
+ it is added to the map. When no default value specified, and argument is not
+ present in the command line, corresponding key is not present in the resulting
+ map.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="handler"/>
+ <desc>
+ <p>Command handler specification. Called by <seemfa marker="#run/3"><c>run/3</c>
+ </seemfa> upon successful parser return.</p>
+ <taglist>
+ <tag><c>fun((arg_map()) -> term())</c></tag>
+ <item><p>
+ Function accepting <seetype marker="#arg_map"><c>argument map</c></seetype>.
+ See the basic example in the <seeerl marker="#quick-start">Quick Start</seeerl>
+ section.
+ </p></item>
+ <tag><c>{Module :: module(), Function :: atom()}</c></tag>
+ <item><p>
+ Function named <c>Function</c>, exported from <c>Module</c>, accepting
+ <seetype marker="#arg_map"><c>argument map</c></seetype>.
+ </p></item>
+ <tag><c>{fun(() -> term()), Default :: term()}</c></tag>
+ <item><p>
+ Function accepting as many arguments as there are in the <c>arguments</c>
+ list for this command. Arguments missing from the parsed map are replaced
+ with the <c>Default</c>. Convenient way to expose existing functions.
+ </p>
+ <code>
+1> Cmd = #{arguments => [
+ #{name => x, type => float},
+ #{name => y, type => float, short => $p}],
+ handler => {fun math:pow/2, 1}},
+argparse:run(["2", "-p", "3"], Cmd, #{}).
+
+8.0
+
+%% default term 1 is passed to math:pow/2
+2> argparse:run(["2"], Cmd, #{}).
+
+2.0
+ </code>
+ </item>
+ <tag><c>{Module :: module(), Function :: atom(), Default :: term()}</c></tag>
+ <item><p>Function named <c>Function</c>, exported from <c>Module</c>, accepting
+ as many arguments as defined for this command. Arguments missing from the parsed
+ map are replaced with the <c>Default</c>. Effectively, just a different syntax
+ to the same functionality as demonstrated in the code above.</p></item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="command_help"/>
+ <desc>
+ <p>User-defined help template. Use this option to mix custom and predefined usage text.
+ Help template may contain unicode strings, and following atoms:</p>
+ <taglist>
+ <tag>usage</tag>
+ <item><p>
+ Formatted command line usage text, e.g. <c>rm [-rf] &lt;directory&gt;</c>.
+ </p></item>
+ <tag>commands</tag>
+ <item><p>
+ Expanded list of sub-commands.
+ </p></item>
+ <tag>arguments</tag>
+ <item><p>
+ Detailed description of positional arguments.
+ </p></item>
+ <tag>options</tag>
+ <item><p>
+ Detailed description of optional arguments.
+ </p></item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="command"/>
+ <desc>
+ <p>Command specification. May contain nested commands, forming a hierarchy.</p>
+ <taglist>
+ <tag><c>commands</c></tag>
+ <item><p>
+ Maps of nested commands. Keys must be strings, matching command line input.
+ Basic utilities do not need to specify any nested commands.
+ </p>
+ </item>
+ <tag><c>arguments</c></tag>
+ <item><p>
+ List of arguments accepted by this command, and all nested commands in the
+ hierarchy.
+ </p></item>
+ <tag><c>help</c></tag>
+ <item><p>
+ Specifies help/usage text for this command. Pass <c>hidden</c> to remove
+ this command from the usage output.
+ </p></item>
+ <tag><c>handler</c></tag>
+ <item><p>
+ Specifies a callback function to call by <seemfa marker="#run/3">run/3</seemfa>
+ when the parser is successful.
+ </p></item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="cmd_path"/>
+ <desc>
+ <p>Path to the nested command. First element is always the <c>progname</c>,
+ subsequent elements are nested command names.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="parser_error"/>
+ <desc>
+ <p>Returned from <seemfa marker="#parse/3"><c>parse/2,3</c></seemfa> when the
+ user input cannot be parsed according to the command specification.</p>
+ <p>First element is the path to the command that was considered when the
+ parser detected an error. Second element, <c>Expected</c>, is the argument
+ specification that caused an error. It could be <c>undefined</c>, meaning
+ that <c>Actual</c> argument had no corresponding specification in the
+ arguments list for the current command. </p>
+ <p>When <c>Actual</c> is set to <c>undefined</c>, it means that a required
+ argument is missing from the command line. If both <c>Expected</c> and
+ <c>Actual</c> have values, it means validation error.</p>
+ <p>Use <seemfa marker="#format_error/1"><c>format_error/1</c></seemfa> to
+ generate a human-readable error description, unless there is a need to
+ provide localised error messages.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="parser_options"/>
+ <desc>
+ <p>Options changing parser behaviour.</p>
+ <taglist>
+ <tag><c>prefixes</c></tag>
+ <item><p>
+ Changes the option prefix (the default is <c>-</c>).
+ </p></item>
+ <tag><c>default</c></tag>
+ <item><p>
+ Specifies the default value for all optional arguments. When
+ this field is set, resulting argument map will contain all
+ argument names. Useful for easy pattern matching on the
+ argument map in the handler function.
+ </p></item>
+ <tag><c>progname</c></tag>
+ <item><p>
+ Specifies the program (root command) name. Returned as the
+ first element of the command path, and printed in help/usage
+ text. It is recommended to have this value set, otherwise the
+ default one is determined with <c>init:get_argument(progname)</c>
+ and is often set to <c>erl</c> instead of the actual script name.
+ </p></item>
+ <tag><c>command</c></tag>
+ <item><p>
+ Specifies the path to the nested command for
+ <seemfa marker="#help/2"><c>help/2</c></seemfa>. Useful to
+ limit output for complex utilities with multiple commands,
+ and used by the default error handling logic.
+ </p></item>
+ <tag><c>columns</c></tag>
+ <item><p>
+ Specifies the help/usage text width (characters) for
+ <seemfa marker="#help/2"><c>help/2</c></seemfa>. Default value
+ is 80.
+ </p></item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="parse_result"/>
+ <desc>
+ <p>Returned from <seemfa marker="#parse/3"><c>parse/2,3</c></seemfa>. Contains
+ arguments extracted from the command line, path to the nested command (if any),
+ and a (potentially nested) command specification that was considered when
+ the parser finished successfully. It is expected that the command contains
+ a handler definition, that will be called passing the argument map.</p>
+ </desc>
+ </datatype>
+
+ </datatypes>
+
+ <funcs>
+
+ <func>
+ <name name="format_error" arity="1" since="OTP 26.0"/>
+ <fsummary>Generates human-readable text for parser errors.</fsummary>
+ <desc>
+ <p>Generates human-readable text for
+ <seetype marker="#parser_error"><c>parser error</c></seetype>. Does
+ not include help/usage information, and does not provide localisation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="help" arity="1" since="OTP 26.0"/>
+ <name name="help" arity="2" since="OTP 26.0"/>
+ <fsummary>Generates help/usage information text.</fsummary>
+ <desc>
+ <p>Generates help/usage information text for the command
+ supplied, or any nested command when <c>command</c>
+ option is specified. Does not provide localisaton.
+ Expects <c>progname</c> to be set, otherwise defaults to
+ return value of <c>init:get_argument(progname)</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="parse" arity="2" since="OTP 26.0"/>
+ <name name="parse" arity="3" since="OTP 26.0"/>
+ <fsummary>Parses command line arguments according to the command specification.</fsummary>
+ <desc>
+ <p>Parses command line arguments according to the command specification.
+ Raises an exception if the command specification is not valid. Use
+ <seemfa marker="erl_error#format_exception/3"><c>erl_error:format_exception/3,4</c>
+ </seemfa> to see a friendlier message. Invalid command line input
+ does not raise an exception, but makes <c>parse/2,3</c> to return a tuple
+ <seetype marker="#parser_error"><c>{error, parser_error()}</c></seetype>.
+ </p>
+ <p>This function does not call command handler.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="run" arity="3" since="OTP 26.0"/>
+ <fsummary>Parses command line arguments and calls the matching command handler.</fsummary>
+ <desc>
+ <p>Parses command line arguments and calls the matching command handler.
+ Prints human-readable error, help/usage information for the discovered
+ command, and halts the emulator with code 1 if there is any error in the
+ command specification or user-provided command line input.
+ </p>
+ <warning>
+ <p>This function is designed to work as an entry point to a standalone
+ <seecom marker="erts:escript"><c>escript</c></seecom>. Therefore, it halts
+ the emulator for any error detected. Do not use this function through
+ remote procedure call, or it may result in an unexpected shutdown of a remote
+ node.</p>
+ </warning>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
+
diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml
index 3477c2c90e..283c3f9198 100644
--- a/lib/stdlib/doc/src/gb_sets.xml
+++ b/lib/stdlib/doc/src/gb_sets.xml
@@ -68,48 +68,10 @@
<section>
<title>Compatibility</title>
- <p>The following functions in this module also exist and provides
- the same functionality in the
- <seeerl marker="sets"><c>sets(3)</c></seeerl> and
- <seeerl marker="ordsets"><c>ordsets(3)</c></seeerl>
- modules. That is, by only changing the module name for each call,
- you can try out different set representations.</p>
- <list type="bulleted">
- <item><seemfa marker="#add_element/2"><c>add_element/2</c></seemfa>
- </item>
- <item><seemfa marker="#del_element/2"><c>del_element/2</c></seemfa>
- </item>
- <item><seemfa marker="#filter/2"><c>filter/2</c></seemfa>
- </item>
- <item><seemfa marker="#fold/3"><c>fold/3</c></seemfa>
- </item>
- <item><seemfa marker="#from_list/1"><c>from_list/1</c></seemfa>
- </item>
- <item><seemfa marker="#intersection/1"><c>intersection/1</c></seemfa>
- </item>
- <item><seemfa marker="#intersection/2"><c>intersection/2</c></seemfa>
- </item>
- <item><seemfa marker="#is_element/2"><c>is_element/2</c></seemfa>
- </item>
- <item><seemfa marker="#is_empty/1"><c>is_empty/1</c></seemfa>
- </item>
- <item><seemfa marker="#is_set/1"><c>is_set/1</c></seemfa>
- </item>
- <item><seemfa marker="#is_subset/2"><c>is_subset/2</c></seemfa>
- </item>
- <item><seemfa marker="#new/0"><c>new/0</c></seemfa>
- </item>
- <item><seemfa marker="#size/1"><c>size/1</c></seemfa>
- </item>
- <item><seemfa marker="#subtract/2"><c>subtract/2</c></seemfa>
- </item>
- <item><seemfa marker="#to_list/1"><c>to_list/1</c></seemfa>
- </item>
- <item><seemfa marker="#union/1"><c>union/1</c></seemfa>
- </item>
- <item><seemfa marker="#union/2"><c>union/2</c></seemfa>
- </item>
- </list>
+ <p>See the <seeerl marker="sets#compatibility">Compatibility Section
+ in the <c>sets(3)</c> module</seeerl> for information about
+ the compatibility of the different implementations of sets in the
+ Standard Library.</p>
</section>
<datatypes>
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index 342fcb8b3d..25d02d83f9 100644
--- a/lib/stdlib/doc/src/gen_event.xml
+++ b/lib/stdlib/doc/src/gen_event.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2022</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 403abf2be8..0906db1359 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -31,6 +31,22 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 4.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The type specs in the <c>erl_parse</c> module has been
+ updated to include the <c>maybe</c> construct and the
+ <c>!</c> operator.</p>
+ <p>
+ Own Id: OTP-18506 Aux Id: GH-6956 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/doc/src/orddict.xml b/lib/stdlib/doc/src/orddict.xml
index 74ae55de3b..46370358e6 100644
--- a/lib/stdlib/doc/src/orddict.xml
+++ b/lib/stdlib/doc/src/orddict.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2020</year>
+ <year>2000</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/ordsets.xml b/lib/stdlib/doc/src/ordsets.xml
index 35127dcf95..7b02d13ab3 100644
--- a/lib/stdlib/doc/src/ordsets.xml
+++ b/lib/stdlib/doc/src/ordsets.xml
@@ -48,6 +48,11 @@
that while <c>sets</c> considers two elements as different if they
do not match (<c>=:=</c>), this module considers two elements as
different if and only if they do not compare equal (<c>==</c>).</p>
+
+ <p>See the <seeerl marker="sets#compatibility">Compatibility Section
+ in the <c>sets(3)</c> module</seeerl> for more information about
+ the compatibility of the different implementations of sets in the
+ Standard Library.</p>
</description>
<datatypes>
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index 1d52463481..a064c8341e 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -230,8 +230,8 @@ init(Parent) ->
</func>
<func>
- <name since="OTP-26.0">init_fail(Ret, Exception) -> no_return()</name>
- <name since="OTP-26.0">init_fail(Parent, Ret, Exception) -> no_return()</name>
+ <name since="OTP 26.0">init_fail(Ret, Exception) -> no_return()</name>
+ <name since="OTP 26.0">init_fail(Parent, Ret, Exception) -> no_return()</name>
<fsummary>Used by a process that fails to start.</fsummary>
<type>
<v>Parent = <seetype marker="erts:erlang#pid">pid()</seetype></v>
diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml
index b5fe0dc512..480ca89963 100644
--- a/lib/stdlib/doc/src/queue.xml
+++ b/lib/stdlib/doc/src/queue.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2022</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/ref_man.xml b/lib/stdlib/doc/src/ref_man.xml
index 961c5a0a77..04990db408 100644
--- a/lib/stdlib/doc/src/ref_man.xml
+++ b/lib/stdlib/doc/src/ref_man.xml
@@ -32,6 +32,7 @@
<description>
</description>
<xi:include href="stdlib_app.xml"/>
+ <xi:include href="argparse.xml"/>
<xi:include href="array.xml"/>
<xi:include href="assert_hrl.xml"/>
<xi:include href="base64.xml"/>
diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml
index 53b64a3ac0..b3899c440f 100644
--- a/lib/stdlib/doc/src/sets.xml
+++ b/lib/stdlib/doc/src/sets.xml
@@ -69,6 +69,71 @@
</description>
+ <section>
+ <title>Compatibility</title>
+ <p>The following functions in this module also exist and provide
+ the same functionality in the
+ <seeerl marker="gb_sets"><c>gb_sets(3)</c></seeerl> and
+ <seeerl marker="ordsets"><c>ordsets(3)</c></seeerl>
+ modules. That is, by only changing the module name for each call,
+ you can try out different set representations.</p>
+ <list type="bulleted">
+ <item><seemfa marker="#add_element/2"><c>add_element/2</c></seemfa>
+ </item>
+ <item><seemfa marker="#del_element/2"><c>del_element/2</c></seemfa>
+ </item>
+ <item><seemfa marker="#filter/2"><c>filter/2</c></seemfa>
+ </item>
+ <item><seemfa marker="#fold/3"><c>fold/3</c></seemfa>
+ </item>
+ <item><seemfa marker="#from_list/1"><c>from_list/1</c></seemfa>
+ </item>
+ <item><seemfa marker="#intersection/1"><c>intersection/1</c></seemfa>
+ </item>
+ <item><seemfa marker="#intersection/2"><c>intersection/2</c></seemfa>
+ </item>
+ <item><seemfa marker="#is_element/2"><c>is_element/2</c></seemfa>
+ </item>
+ <item><seemfa marker="#is_empty/1"><c>is_empty/1</c></seemfa>
+ </item>
+ <item><seemfa marker="#is_set/1"><c>is_set/1</c></seemfa>
+ </item>
+ <item><seemfa marker="#is_subset/2"><c>is_subset/2</c></seemfa>
+ </item>
+ <item><seemfa marker="#new/0"><c>new/0</c></seemfa>
+ </item>
+ <item><seemfa marker="#size/1"><c>size/1</c></seemfa>
+ </item>
+ <item><seemfa marker="#subtract/2"><c>subtract/2</c></seemfa>
+ </item>
+ <item><seemfa marker="#to_list/1"><c>to_list/1</c></seemfa>
+ </item>
+ <item><seemfa marker="#union/1"><c>union/1</c></seemfa>
+ </item>
+ <item><seemfa marker="#union/2"><c>union/2</c></seemfa>
+ </item>
+ </list>
+ <note>
+ <p>
+ While the three set implementations offer the same <em>functionality</em>
+ with respect to the aforementioned functions, their overall <em>behavior</em>
+ may differ. As mentioned, this module considers elements as different if
+ and only if they do not match (<c>=:=</c>), while both
+ <seeerl marker="ordsets"><c>ordsets</c></seeerl> and
+ <seeerl marker="gb_sets"><c>gb_sets</c></seeerl> consider elements as
+ different if and only if they do not compare equal (<c>==</c>).
+ </p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input>sets:is_element(1.0, sets:from_list([1])).</input>
+false
+2> <input>ordsets:is_element(1.0, ordsets:from_list([1])).</input>
+true
+2> <input>gb_sets:is_element(1.0, gb_sets:from_list([1])).</input>
+true</pre>
+ </note>
+ </section>
+
<datatypes>
<datatype>
<name name="set" n_vars="1"/>
diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml
index 8279c5a5d8..fc19db4bf3 100644
--- a/lib/stdlib/doc/src/specs.xml
+++ b/lib/stdlib/doc/src/specs.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_argparse.xml"/>
<xi:include href="../specs/specs_array.xml"/>
<xi:include href="../specs/specs_base64.xml"/>
<xi:include href="../specs/specs_beam_lib.xml"/>
diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile
index e546172856..abdb665b09 100644
--- a/lib/stdlib/src/Makefile
+++ b/lib/stdlib/src/Makefile
@@ -42,6 +42,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/stdlib-$(VSN)
# ----------------------------------------------------
MODULES= \
array \
+ argparse \
base64 \
beam_lib \
binary \
diff --git a/lib/stdlib/src/argparse.erl b/lib/stdlib/src/argparse.erl
new file mode 100644
index 0000000000..a5fdd8d3d9
--- /dev/null
+++ b/lib/stdlib/src/argparse.erl
@@ -0,0 +1,1357 @@
+%%
+%%
+%% Copyright Maxim Fedorov
+%%
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+
+-module(argparse).
+-author("maximfca@gmail.com").
+
+%% API Exports
+-export([
+ run/3,
+ parse/2, parse/3,
+ help/1, help/2,
+ format_error/1
+]).
+
+%% Internal exports for validation and error reporting.
+-export([validate/1, validate/2, format_error/2]).
+
+%%--------------------------------------------------------------------
+%% API
+
+-type arg_type() ::
+ boolean |
+ float |
+ {float, Choice :: [float()]} |
+ {float, [{min, float()} | {max, float()}]} |
+ integer |
+ {integer, Choices :: [integer()]} |
+ {integer, [{min, integer()} | {max, integer()}]} |
+ string |
+ {string, Choices :: [string()]} |
+ {string, Re :: string()} |
+ {string, Re :: string(), ReOptions :: [term()]} |
+ binary |
+ {binary, Choices :: [binary()]} |
+ {binary, Re :: binary()} |
+ {binary, Re :: binary(), ReOptions :: [term()]} |
+ atom |
+ {atom, Choices :: [atom()]} |
+ {atom, unsafe} |
+ {custom, fun((string()) -> term())}.
+%% Built-in types include basic validation abilities
+%% String and binary validation may use regex match (ignoring captured value).
+%% For float, integer, string, binary and atom type, it is possible to specify
+%% available choices instead of regex/min/max.
+
+-type argument_help() :: {
+ unicode:chardata(), %% short form, printed in command usage, e.g. "[--dir <dirname>]", developer is
+ %% responsible for proper formatting (e.g. adding <>, dots... and so on)
+ [unicode:chardata() | type | default] | fun(() -> unicode:chardata())
+}.
+%% Help template definition for argument. Short and long forms exist for every argument.
+%% Short form is printed together with command definition, e.g. "usage: rm [--force]",
+%% while long description is printed in detailed section below: "--force forcefully remove".
+
+-type argument_name() :: atom() | string() | binary().
+
+-type argument() :: #{
+ %% Argument name, and a destination to store value too
+ %% It is allowed to have several arguments named the same, setting or appending to the same variable.
+ name := argument_name(),
+
+ %% short, single-character variant of command line option, omitting dash (example: $b, meaning -b),
+ %% when present, the argument is considered optional
+ short => char(),
+
+ %% long command line option, omitting first dash (example: "kernel" means "-kernel" in the command line)
+ %% long command always wins over short abbreviation (e.g. -kernel is considered before -k -e -r -n -e -l)
+ %% when present, the argument is considered optional
+ long => string(),
+
+ %% makes parser to return an error if the argument is not present in the command line
+ required => boolean(),
+
+ %% default value, produced if the argument is not present in the command line
+ %% parser also accepts a global default
+ default => term(),
+
+ %% parameter type (string by default)
+ type => arg_type(),
+
+ %% action to take when argument is matched
+ action => store | %% default: store argument consumed (last stored wins)
+ {store, term()} | %% does not consume argument, stores term() instead
+ append | %% appends consumed argument to a list
+ {append, term()} | %% does not consume an argument, appends term() to a list
+ count | %% does not consume argument, bumps counter
+ extend, %% uses when nargs is list/nonempty_list/all - appends every element to the list
+
+ %% how many positional arguments to consume
+ nargs =>
+ pos_integer() | %% consume exactly this amount, e.g. '-kernel key value' #{long => "-kernel", args => 2}
+ %% returns #{kernel => ["key", "value"]}
+ 'maybe' | %% if the next argument is positional, consume it, otherwise produce default
+ {'maybe', term()} | %% if the next argument is positional, consume it, otherwise produce term()
+ list | %% consume zero or more positional arguments, until next optional
+ nonempty_list | %% consume at least one positional argument, until next optional
+ all, %% fold remaining command line into this argument
+
+ %% help string printed in usage, hidden help is not printed at all
+ help => hidden | unicode:chardata() | argument_help()
+}.
+%% Command line argument specification.
+%% Argument can be optional - starting with - (dash), and positional.
+
+-type arg_map() :: #{argument_name() => term()}.
+%% Arguments map: argument name to a term, produced by parser. Supplied to the command handler
+
+-type handler() ::
+ optional | %% valid for commands with sub-commands, suppresses parser error when no
+ %% sub-command is selected
+ fun((arg_map()) -> term()) | %% handler accepting arg_map
+ {module(), Fn :: atom()} | %% handler, accepting arg_map, Fn exported from module()
+ {fun(() -> term()), term()} | %% handler, positional form (term() is supplied for omitted args)
+ {module(), atom(), term()}. %% handler, positional form, exported from module()
+%% Command handler. May produce some output. Can accept a map, or be
+%% arbitrary mfa() for handlers accepting positional list.
+%% Special value 'optional' may be used to suppress an error that
+%% otherwise raised when command contains sub-commands, but arguments
+%% supplied via command line do not select any.
+
+-type command_help() :: [unicode:chardata() | usage | commands | arguments | options].
+%% Template for the command help/usage message.
+
+%% Command descriptor
+-type command() :: #{
+ %% Sub-commands are arranged into maps. Command name must not start with <em>prefix</em>.
+ commands => #{string() => command()},
+ %% accepted arguments list. Order is important!
+ arguments => [argument()],
+ %% help line
+ help => hidden | unicode:chardata() | command_help(),
+ %% recommended handler function
+ handler => handler()
+}.
+
+-type cmd_path() :: [string()].
+%% Command path, for nested commands
+
+-export_type([arg_type/0, argument_help/0, argument/0,
+ command/0, handler/0, cmd_path/0, arg_map/0]).
+
+-type parser_error() :: {Path :: cmd_path(),
+ Expected :: argument() | undefined,
+ Actual :: string() | undefined,
+ Details :: unicode:chardata()}.
+%% Returned from `parse/2,3' when command spec is valid, but the command line
+%% cannot be parsed using the spec.
+%% When `Expected' is undefined, but `Actual' is not, it means that the input contains
+%% an unexpected argument which cannot be parsed according to command spec.
+%% When `Expected' is an argument, and `Actual' is undefined, it means that a mandatory
+%% argument is not provided in the command line.
+%% When both `Expected' and `Actual' are defined, it means that the supplied argument
+%% is failing validation.
+%% When both are `undefined', there is some logical issue (e.g. a sub-command is required,
+%% but was not selected).
+
+-type parser_options() :: #{
+ %% allowed prefixes (default is [$-]).
+ prefixes => [char()],
+ %% default value for all missing optional arguments
+ default => term(),
+ %% root command name (program name)
+ progname => string() | atom(),
+ %% considered by `help/2' only
+ command => cmd_path(), %% command to print the help for
+ columns => pos_integer() %% viewport width, in characters
+}.
+%% Parser options
+
+-type parse_result() ::
+ {ok, arg_map(), Path :: cmd_path(), command()} |
+ {error, parser_error()}.
+%% Parser result: argument map, path leading to successfully
+%% matching command (contains only ["progname"] if there were
+%% no subcommands matched), and a matching command.
+
+%% @equiv validate(Command, #{})
+-spec validate(command()) -> Progname :: string().
+validate(Command) ->
+ validate(Command, #{}).
+
+%% @doc Validate command specification, taking Options into account.
+%% Raises an error if the command specification is invalid.
+-spec validate(command(), parser_options()) -> Progname :: string().
+validate(Command, Options) ->
+ Prog = executable(Options),
+ is_list(Prog) orelse erlang:error(badarg, [Command, Options],
+ [{error_info, #{cause => #{2 => <<"progname is not valid">>}}}]),
+ Prefixes = maps:from_list([{P, true} || P <- maps:get(prefixes, Options, [$-])]),
+ _ = validate_command([{Prog, Command}], Prefixes),
+ Prog.
+
+%% @equiv parse(Args, Command, #{})
+-spec parse(Args :: [string()], command()) -> parse_result().
+parse(Args, Command) ->
+ parse(Args, Command, #{}).
+
+%% @doc Parses supplied arguments according to expected command specification.
+%% @param Args command line arguments (e.g. `init:get_plain_arguments()')
+%% @returns argument map, or argument map with deepest matched command
+%% definition.
+-spec parse(Args :: [string()], command(), Options :: parser_options()) -> parse_result().
+parse(Args, Command, Options) ->
+ Prog = validate(Command, Options),
+ %% use maps and not sets v2, because sets:is_element/2 cannot be used in guards (unlike is_map_key)
+ Prefixes = maps:from_list([{P, true} || P <- maps:get(prefixes, Options, [$-])]),
+ try
+ parse_impl(Args, merge_arguments(Prog, Command, init_parser(Prefixes, Command, Options)))
+ catch
+ %% Parser error may happen at any depth, and bubbling the error is really
+ %% cumbersome. Use exceptions and catch it before returning from `parse/2,3' instead.
+ throw:Reason ->
+ {error, Reason}
+ end.
+
+%% @equiv help(Command, #{})
+-spec help(command()) -> string().
+help(Command) ->
+ help(Command, #{}).
+
+%% @doc Returns help for Command formatted according to Options specified
+-spec help(command(), parser_options()) -> unicode:chardata().
+help(Command, Options) ->
+ Prog = validate(Command, Options),
+ format_help({Prog, Command}, Options).
+
+%% @doc
+-spec run(Args :: [string()], command(), parser_options()) -> term().
+run(Args, Command, Options) ->
+ try parse(Args, Command, Options) of
+ {ok, ArgMap, Path, SubCmd} ->
+ handle(Command, ArgMap, tl(Path), SubCmd);
+ {error, Reason} ->
+ io:format("error: ~ts~n", [argparse:format_error(Reason)]),
+ io:format("~ts", [argparse:help(Command, Options#{command => tl(element(1, Reason))})]),
+ erlang:halt(1)
+ catch
+ error:Reason:Stack ->
+ io:format(erl_error:format_exception(error, Reason, Stack)),
+ erlang:halt(1)
+ end.
+
+%% @doc Basic formatter for the parser error reason.
+-spec format_error(Reason :: parser_error()) -> unicode:chardata().
+format_error({Path, undefined, undefined, Details}) ->
+ io_lib:format("~ts: ~ts", [format_path(Path), Details]);
+format_error({Path, undefined, Actual, Details}) ->
+ io_lib:format("~ts: unknown argument: ~ts~ts", [format_path(Path), Actual, Details]);
+format_error({Path, #{name := Name}, undefined, Details}) ->
+ io_lib:format("~ts: required argument missing: ~ts~ts", [format_path(Path), Name, Details]);
+format_error({Path, #{name := Name}, Value, Details}) ->
+ io_lib:format("~ts: invalid argument for ~ts: ~ts ~ts", [format_path(Path), Name, Value, Details]).
+
+-type validator_error() ::
+ {?MODULE, command | argument, cmd_path(), Field :: atom(), Detail :: unicode:chardata()}.
+
+%% @doc Transforms exception thrown by `validate/1,2' according to EEP54.
+%% Use `erl_error:format_exception/3,4' to get the shell-like output.
+-spec format_error(Reason :: validator_error(), erlang:stacktrace()) -> map().
+format_error({?MODULE, command, Path, Field, Reason}, [{_M, _F, [Cmd], Info} | _]) ->
+ #{cause := Cause} = proplists:get_value(error_info, Info, #{}),
+ Cause#{general => <<"command specification is invalid">>, 1 => io_lib:format("~tp", [Cmd]),
+ reason => io_lib:format("command \"~ts\": invalid field '~ts', reason: ~ts", [format_path(Path), Field, Reason])};
+format_error({?MODULE, argument, Path, Field, Reason}, [{_M, _F, [Arg], Info} | _]) ->
+ #{cause := Cause} = proplists:get_value(error_info, Info, #{}),
+ ArgName = maps:get(name, Arg, ""),
+ Cause#{general => "argument specification is invalid", 1 => io_lib:format("~tp", [Arg]),
+ reason => io_lib:format("command \"~ts\", argument '~ts', invalid field '~ts': ~ts",
+ [format_path(Path), ArgName, Field, Reason])}.
+
+%%--------------------------------------------------------------------
+%% Parser implementation
+
+%% Parser state (not available via API)
+-record(eos, {
+ %% prefix character map, by default, only -
+ prefixes :: #{char() => true},
+ %% argument map to be returned
+ argmap = #{} :: arg_map(),
+ %% sub-commands, in reversed orders, allowing to recover the path taken
+ commands = [] :: cmd_path(),
+ %% command being matched
+ current :: command(),
+ %% unmatched positional arguments, in the expected match order
+ pos = [] :: [argument()],
+ %% expected optional arguments, mapping between short/long form and an argument
+ short = #{} :: #{integer() => argument()},
+ long = #{} :: #{string() => argument()},
+ %% flag, whether there are no options that can be confused with negative numbers
+ no_digits = true :: boolean(),
+ %% global default for not required arguments
+ default :: error | {ok, term()}
+}).
+
+init_parser(Prefixes, Cmd, Options) ->
+ #eos{prefixes = Prefixes, current = Cmd, default = maps:find(default, Options)}.
+
+%% Optional or positional argument?
+-define(IS_OPTION(Arg), is_map_key(short, Arg) orelse is_map_key(long, Arg)).
+
+%% helper function to match either a long form of "--arg=value", or just "--arg"
+match_long(Arg, LongOpts) ->
+ case maps:find(Arg, LongOpts) of
+ {ok, Option} ->
+ {ok, Option};
+ error ->
+ %% see if there is '=' equals sign in the Arg
+ case string:split(Arg, "=") of
+ [MaybeLong, Value] ->
+ case maps:find(MaybeLong, LongOpts) of
+ {ok, Option} ->
+ {ok, Option, Value};
+ error ->
+ nomatch
+ end;
+ _ ->
+ nomatch
+ end
+ end.
+
+%% parse_impl implements entire internal parse logic.
+
+%% Clause: option starting with any prefix
+%% No separate clause for single-character short form, because there could be a single-character
+%% long form taking precedence.
+parse_impl([[Prefix | Name] | Tail], #eos{prefixes = Pref} = Eos) when is_map_key(Prefix, Pref) ->
+ %% match "long" option from the list of currently known
+ case match_long(Name, Eos#eos.long) of
+ {ok, Option} ->
+ consume(Tail, Option, Eos);
+ {ok, Option, Value} ->
+ consume([Value | Tail], Option, Eos);
+ nomatch ->
+ %% try to match single-character flag
+ case Name of
+ [Flag] when is_map_key(Flag, Eos#eos.short) ->
+ %% found a flag
+ consume(Tail, maps:get(Flag, Eos#eos.short), Eos);
+ [Flag | Rest] when is_map_key(Flag, Eos#eos.short) ->
+ %% can be a combination of flags, or flag with value,
+ %% but can never be a negative integer, because otherwise
+ %% it will be reflected in no_digits
+ case abbreviated(Name, [], Eos#eos.short) of
+ false ->
+ %% short option with Rest being an argument
+ consume([Rest | Tail], maps:get(Flag, Eos#eos.short), Eos);
+ Expanded ->
+ %% expand multiple flags into actual list, adding prefix
+ parse_impl([[Prefix,E] || E <- Expanded] ++ Tail, Eos)
+ end;
+ MaybeNegative when Prefix =:= $-, Eos#eos.no_digits ->
+ case is_digits(MaybeNegative) of
+ true ->
+ %% found a negative number
+ parse_positional([Prefix|Name], Tail, Eos);
+ false ->
+ catch_all_positional([[Prefix|Name] | Tail], Eos)
+ end;
+ _Unknown ->
+ catch_all_positional([[Prefix|Name] | Tail], Eos)
+ end
+ end;
+
+%% Arguments not starting with Prefix: attempt to match sub-command, if available
+parse_impl([Positional | Tail], #eos{current = #{commands := SubCommands}} = Eos) ->
+ case maps:find(Positional, SubCommands) of
+ error ->
+ %% sub-command not found, try positional argument
+ parse_positional(Positional, Tail, Eos);
+ {ok, SubCmd} ->
+ %% found matching sub-command with arguments, descend into it
+ parse_impl(Tail, merge_arguments(Positional, SubCmd, Eos))
+ end;
+
+%% Clause for arguments that don't have sub-commands (therefore check for
+%% positional argument).
+parse_impl([Positional | Tail], Eos) ->
+ parse_positional(Positional, Tail, Eos);
+
+%% Entire command line has been matched, go over missing arguments,
+%% add defaults etc
+parse_impl([], #eos{argmap = ArgMap0, commands = Commands, current = Current, pos = Pos, default = Def} = Eos) ->
+ %% error if stopped at sub-command with no handler
+ map_size(maps:get(commands, Current, #{})) >0 andalso
+ (not is_map_key(handler, Current)) andalso
+ throw({Commands, undefined, undefined, <<"subcommand expected">>}),
+
+ %% go over remaining positional, verify they are all not required
+ ArgMap1 = fold_args_map(Commands, true, ArgMap0, Pos, Def),
+ %% go over optionals, and either raise an error, or set default
+ ArgMap2 = fold_args_map(Commands, false, ArgMap1, maps:values(Eos#eos.short), Def),
+ ArgMap3 = fold_args_map(Commands, false, ArgMap2, maps:values(Eos#eos.long), Def),
+
+ %% return argument map, command path taken, and the deepest
+ %% last command matched (usually it contains a handler to run)
+ {ok, ArgMap3, Eos#eos.commands, Eos#eos.current}.
+
+%% Generate error for missing required argument, and supply defaults for
+%% missing optional arguments that have defaults.
+fold_args_map(Commands, Req, ArgMap, Args, GlobalDefault) ->
+ lists:foldl(
+ fun (#{name := Name}, Acc) when is_map_key(Name, Acc) ->
+ %% argument present
+ Acc;
+ (#{required := true} = Opt, _Acc) ->
+ %% missing, and required explicitly
+ throw({Commands, Opt, undefined, <<>>});
+ (#{name := Name, required := false, default := Default}, Acc) ->
+ %% explicitly not required argument with default
+ Acc#{Name => Default};
+ (#{name := Name, required := false}, Acc) ->
+ %% explicitly not required with no local default, try global one
+ try_global_default(Name, Acc, GlobalDefault);
+ (#{name := Name, default := Default}, Acc) when Req =:= true ->
+ %% positional argument with default
+ Acc#{Name => Default};
+ (Opt, _Acc) when Req =:= true ->
+ %% missing, for positional argument, implicitly required
+ throw({Commands, Opt, undefined, <<>>});
+ (#{name := Name, default := Default}, Acc) ->
+ %% missing, optional, and there is a default
+ Acc#{Name => Default};
+ (#{name := Name}, Acc) ->
+ %% missing, optional, no local default, try global default
+ try_global_default(Name, Acc, GlobalDefault)
+ end, ArgMap, Args).
+
+try_global_default(_Name, Acc, error) ->
+ Acc;
+try_global_default(Name, Acc, {ok, Term}) ->
+ Acc#{Name => Term}.
+
+%%--------------------------------------------------------------------
+%% argument consumption (nargs) handling
+
+catch_all_positional(Tail, #eos{pos = [#{nargs := all} = Opt]} = Eos) ->
+ action([], Tail, Opt#{type => {list, maps:get(type, Opt, string)}}, Eos);
+%% it is possible that some positional arguments are not required,
+%% and therefore it is possible to catch all skipping those
+catch_all_positional(Tail, #eos{argmap = Args, pos = [#{name := Name, default := Default, required := false} | Pos]} = Eos) ->
+ catch_all_positional(Tail, Eos#eos{argmap = Args#{Name => Default}, pos = Pos});
+%% same as above, but no default specified
+catch_all_positional(Tail, #eos{pos = [#{required := false} | Pos]} = Eos) ->
+ catch_all_positional(Tail, Eos#eos{pos = Pos});
+catch_all_positional([Arg | _Tail], #eos{commands = Commands}) ->
+ throw({Commands, undefined, Arg, <<>>}).
+
+parse_positional(Arg, _Tail, #eos{pos = [], commands = Commands}) ->
+ throw({Commands, undefined, Arg, <<>>});
+parse_positional(Arg, Tail, #eos{pos = Pos} = Eos) ->
+ %% positional argument itself is a value
+ consume([Arg | Tail], hd(Pos), Eos).
+
+%% Adds CmdName to path, and includes any arguments found there
+merge_arguments(CmdName, #{arguments := Args} = SubCmd, Eos) ->
+ add_args(Args, Eos#eos{current = SubCmd, commands = Eos#eos.commands ++ [CmdName]});
+merge_arguments(CmdName, SubCmd, Eos) ->
+ Eos#eos{current = SubCmd, commands = Eos#eos.commands ++ [CmdName]}.
+
+%% adds arguments into current set of discovered pos/opts
+add_args([], Eos) ->
+ Eos;
+add_args([#{short := S, long := L} = Option | Tail], #eos{short = Short, long = Long} = Eos) ->
+ %% remember if this option can be confused with negative number
+ NoDigits = no_digits(Eos#eos.no_digits, Eos#eos.prefixes, S, L),
+ add_args(Tail, Eos#eos{short = Short#{S => Option}, long = Long#{L => Option}, no_digits = NoDigits});
+add_args([#{short := S} = Option | Tail], #eos{short = Short} = Eos) ->
+ %% remember if this option can be confused with negative number
+ NoDigits = no_digits(Eos#eos.no_digits, Eos#eos.prefixes, S, 0),
+ add_args(Tail, Eos#eos{short = Short#{S => Option}, no_digits = NoDigits});
+add_args([#{long := L} = Option | Tail], #eos{long = Long} = Eos) ->
+ %% remember if this option can be confused with negative number
+ NoDigits = no_digits(Eos#eos.no_digits, Eos#eos.prefixes, 0, L),
+ add_args(Tail, Eos#eos{long = Long#{L => Option}, no_digits = NoDigits});
+add_args([PosOpt | Tail], #eos{pos = Pos} = Eos) ->
+ add_args(Tail, Eos#eos{pos = Pos ++ [PosOpt]}).
+
+%% If no_digits is still true, try to find out whether it should turn false,
+%% because added options look like negative numbers, and prefixes include -
+no_digits(false, _, _, _) ->
+ false;
+no_digits(true, Prefixes, _, _) when not is_map_key($-, Prefixes) ->
+ true;
+no_digits(true, _, Short, _) when Short >= $0, Short =< $9 ->
+ false;
+no_digits(true, _, _, Long) ->
+ not is_digits(Long).
+
+%%--------------------------------------------------------------------
+%% additional functions for optional arguments processing
+
+%% Returns true when option (!) description passed requires a positional argument,
+%% hence cannot be treated as a flag.
+requires_argument(#{nargs := {'maybe', _Term}}) ->
+ false;
+requires_argument(#{nargs := 'maybe'}) ->
+ false;
+requires_argument(#{nargs := _Any}) ->
+ true;
+requires_argument(Opt) ->
+ case maps:get(action, Opt, store) of
+ store ->
+ maps:get(type, Opt, string) =/= boolean;
+ append ->
+ maps:get(type, Opt, string) =/= boolean;
+ _ ->
+ false
+ end.
+
+%% Attempts to find if passed list of flags can be expanded
+abbreviated([Last], Acc, AllShort) when is_map_key(Last, AllShort) ->
+ lists:reverse([Last | Acc]);
+abbreviated([_], _Acc, _Eos) ->
+ false;
+abbreviated([Flag | Tail], Acc, AllShort) ->
+ case maps:find(Flag, AllShort) of
+ error ->
+ false;
+ {ok, Opt} ->
+ case requires_argument(Opt) of
+ true ->
+ false;
+ false ->
+ abbreviated(Tail, [Flag | Acc], AllShort)
+ end
+ end.
+
+%%--------------------------------------------------------------------
+%% argument consumption (nargs) handling
+
+%% consume predefined amount (none of which can be an option?)
+consume(Tail, #{nargs := Count} = Opt, Eos) when is_integer(Count) ->
+ {Consumed, Remain} = split_to_option(Tail, Count, Eos, []),
+ length(Consumed) < Count andalso
+ throw({Eos#eos.commands, Opt, Tail,
+ io_lib:format("expected ~b, found ~b argument(s)", [Count, length(Consumed)])}),
+ action(Remain, Consumed, Opt#{type => {list, maps:get(type, Opt, string)}}, Eos);
+
+%% handle 'reminder' by just dumping everything in
+consume(Tail, #{nargs := all} = Opt, Eos) ->
+ action([], Tail, Opt#{type => {list, maps:get(type, Opt, string)}}, Eos);
+
+%% require at least one argument
+consume(Tail, #{nargs := nonempty_list} = Opt, Eos) ->
+ {Consumed, Remains} = split_to_option(Tail, -1, Eos, []),
+ Consumed =:= [] andalso throw({Eos#eos.commands, Opt, Tail, <<"expected argument">>}),
+ action(Remains, Consumed, Opt#{type => {list, maps:get(type, Opt, string)}}, Eos);
+
+%% consume all until next option
+consume(Tail, #{nargs := list} = Opt, Eos) ->
+ {Consumed, Remains} = split_to_option(Tail, -1, Eos, []),
+ action(Remains, Consumed, Opt#{type => {list, maps:get(type, Opt, string)}}, Eos);
+
+%% maybe consume one, maybe not...
+%% special cases for 'boolean maybe', only consume 'true' and 'false'
+consume(["true" | Tail], #{type := boolean} = Opt, Eos) ->
+ action(Tail, true, Opt#{type => raw}, Eos);
+consume(["false" | Tail], #{type := boolean} = Opt, Eos) ->
+ action(Tail, false, Opt#{type => raw}, Eos);
+consume(Tail, #{type := boolean} = Opt, Eos) ->
+ %% neither true nor false means 'undefined' (with the default for boolean being true)
+ action(Tail, undefined, Opt, Eos);
+
+%% maybe behaviour, as '?'
+consume(Tail, #{nargs := 'maybe'} = Opt, Eos) ->
+ case split_to_option(Tail, 1, Eos, []) of
+ {[], _} ->
+ %% no argument given, produce default argument (if not present,
+ %% then produce default value of the specified type)
+ action(Tail, default(Opt), Opt#{type => raw}, Eos);
+ {[Consumed], Remains} ->
+ action(Remains, Consumed, Opt, Eos)
+ end;
+
+%% maybe consume one, maybe not...
+consume(Tail, #{nargs := {'maybe', Const}} = Opt, Eos) ->
+ case split_to_option(Tail, 1, Eos, []) of
+ {[], _} ->
+ action(Tail, Const, Opt, Eos);
+ {[Consumed], Remains} ->
+ action(Remains, Consumed, Opt, Eos)
+ end;
+
+%% default case, which depends on action
+consume(Tail, #{action := count} = Opt, Eos) ->
+ action(Tail, undefined, Opt, Eos);
+
+%% for {store, ...} and {append, ...} don't take argument out
+consume(Tail, #{action := {Act, _Const}} = Opt, Eos) when Act =:= store; Act =:= append ->
+ action(Tail, undefined, Opt, Eos);
+
+%% optional: ensure not to consume another option start
+consume([[Prefix | _] = ArgValue | Tail], Opt, Eos) when ?IS_OPTION(Opt), is_map_key(Prefix, Eos#eos.prefixes) ->
+ case Eos#eos.no_digits andalso is_digits(ArgValue) of
+ true ->
+ action(Tail, ArgValue, Opt, Eos);
+ false ->
+ throw({Eos#eos.commands, Opt, undefined, <<"expected argument">>})
+ end;
+
+consume([ArgValue | Tail], Opt, Eos) ->
+ action(Tail, ArgValue, Opt, Eos);
+
+%% we can only be here if it's optional argument, but there is no value supplied,
+%% and type is not 'boolean' - this is an error!
+consume([], Opt, Eos) ->
+ throw({Eos#eos.commands, Opt, undefined, <<"expected argument">>}).
+
+%% no more arguments for consumption, but last optional may still be action-ed
+%%consume([], Current, Opt, Eos) ->
+%% action([], Current, undefined, Opt, Eos).
+
+%% smart split: ignore arguments that can be parsed as negative numbers,
+%% unless there are arguments that look like negative numbers
+split_to_option([], _, _Eos, Acc) ->
+ {lists:reverse(Acc), []};
+split_to_option(Tail, 0, _Eos, Acc) ->
+ {lists:reverse(Acc), Tail};
+split_to_option([[Prefix | _] = MaybeNumber | Tail] = All, Left,
+ #eos{no_digits = true, prefixes = Prefixes} = Eos, Acc) when is_map_key(Prefix, Prefixes) ->
+ case is_digits(MaybeNumber) of
+ true ->
+ split_to_option(Tail, Left - 1, Eos, [MaybeNumber | Acc]);
+ false ->
+ {lists:reverse(Acc), All}
+ end;
+split_to_option([[Prefix | _] | _] = All, _Left,
+ #eos{no_digits = false, prefixes = Prefixes}, Acc) when is_map_key(Prefix, Prefixes) ->
+ {lists:reverse(Acc), All};
+split_to_option([Head | Tail], Left, Opts, Acc) ->
+ split_to_option(Tail, Left - 1, Opts, [Head | Acc]).
+
+%%--------------------------------------------------------------------
+%% Action handling
+
+action(Tail, ArgValue, #{name := ArgName, action := store} = Opt, #eos{argmap = ArgMap} = Eos) ->
+ Value = convert_type(maps:get(type, Opt, string), ArgValue, Opt, Eos),
+ continue_parser(Tail, Opt, Eos#eos{argmap = ArgMap#{ArgName => Value}});
+
+action(Tail, undefined, #{name := ArgName, action := {store, Value}} = Opt, #eos{argmap = ArgMap} = Eos) ->
+ continue_parser(Tail, Opt, Eos#eos{argmap = ArgMap#{ArgName => Value}});
+
+action(Tail, ArgValue, #{name := ArgName, action := append} = Opt, #eos{argmap = ArgMap} = Eos) ->
+ Value = convert_type(maps:get(type, Opt, string), ArgValue, Opt, Eos),
+ continue_parser(Tail, Opt, Eos#eos{argmap = ArgMap#{ArgName => maps:get(ArgName, ArgMap, []) ++ [Value]}});
+
+action(Tail, undefined, #{name := ArgName, action := {append, Value}} = Opt, #eos{argmap = ArgMap} = Eos) ->
+ continue_parser(Tail, Opt, Eos#eos{argmap = ArgMap#{ArgName => maps:get(ArgName, ArgMap, []) ++ [Value]}});
+
+action(Tail, ArgValue, #{name := ArgName, action := extend} = Opt, #eos{argmap = ArgMap} = Eos) ->
+ Value = convert_type(maps:get(type, Opt, string), ArgValue, Opt, Eos),
+ Extended = maps:get(ArgName, ArgMap, []) ++ Value,
+ continue_parser(Tail, Opt, Eos#eos{argmap = ArgMap#{ArgName => Extended}});
+
+action(Tail, _, #{name := ArgName, action := count} = Opt, #eos{argmap = ArgMap} = Eos) ->
+ continue_parser(Tail, Opt, Eos#eos{argmap = ArgMap#{ArgName => maps:get(ArgName, ArgMap, 0) + 1}});
+
+%% default action is `store' (important to sync the code with the first clause above)
+action(Tail, ArgValue, #{name := ArgName} = Opt, #eos{argmap = ArgMap} = Eos) ->
+ Value = convert_type(maps:get(type, Opt, string), ArgValue, Opt, Eos),
+ continue_parser(Tail, Opt, Eos#eos{argmap = ArgMap#{ArgName => Value}}).
+
+%% pop last positional, unless nargs is list/nonempty_list
+continue_parser(Tail, Opt, Eos) when ?IS_OPTION(Opt) ->
+ parse_impl(Tail, Eos);
+continue_parser(Tail, #{nargs := List}, Eos) when List =:= list; List =:= nonempty_list ->
+ parse_impl(Tail, Eos);
+continue_parser(Tail, _Opt, Eos) ->
+ parse_impl(Tail, Eos#eos{pos = tl(Eos#eos.pos)}).
+
+%%--------------------------------------------------------------------
+%% Type conversion
+
+%% Handle "list" variant for nargs returning list
+convert_type({list, Type}, Arg, Opt, Eos) ->
+ [convert_type(Type, Var, Opt, Eos) || Var <- Arg];
+
+%% raw - no conversion applied (most likely default)
+convert_type(raw, Arg, _Opt, _Eos) ->
+ Arg;
+
+%% Handle actual types
+convert_type(string, Arg, _Opt, _Eos) ->
+ Arg;
+convert_type({string, Choices}, Arg, Opt, Eos) when is_list(Choices), is_list(hd(Choices)) ->
+ lists:member(Arg, Choices) orelse
+ throw({Eos#eos.commands, Opt, Arg, <<"is not one of the choices">>}),
+ Arg;
+convert_type({string, Re}, Arg, Opt, Eos) ->
+ case re:run(Arg, Re) of
+ {match, _X} -> Arg;
+ _ -> throw({Eos#eos.commands, Opt, Arg, <<"does not match">>})
+ end;
+convert_type({string, Re, ReOpt}, Arg, Opt, Eos) ->
+ case re:run(Arg, Re, ReOpt) of
+ match -> Arg;
+ {match, _} -> Arg;
+ _ -> throw({Eos#eos.commands, Opt, Arg, <<"does not match">>})
+ end;
+convert_type(integer, Arg, Opt, Eos) ->
+ get_int(Arg, Opt, Eos);
+convert_type({integer, Opts}, Arg, Opt, Eos) ->
+ minimax(get_int(Arg, Opt, Eos), Opts, Eos, Opt, Arg);
+convert_type(boolean, "true", _Opt, _Eos) ->
+ true;
+convert_type(boolean, undefined, _Opt, _Eos) ->
+ true;
+convert_type(boolean, "false", _Opt, _Eos) ->
+ false;
+convert_type(boolean, Arg, Opt, Eos) ->
+ throw({Eos#eos.commands, Opt, Arg, <<"is not a boolean">>});
+convert_type(binary, Arg, _Opt, _Eos) ->
+ unicode:characters_to_binary(Arg);
+convert_type({binary, Choices}, Arg, Opt, Eos) when is_list(Choices), is_binary(hd(Choices)) ->
+ Conv = unicode:characters_to_binary(Arg),
+ lists:member(Conv, Choices) orelse
+ throw({Eos#eos.commands, Opt, Arg, <<"is not one of the choices">>}),
+ Conv;
+convert_type({binary, Re}, Arg, Opt, Eos) ->
+ case re:run(Arg, Re) of
+ {match, _X} -> unicode:characters_to_binary(Arg);
+ _ -> throw({Eos#eos.commands, Opt, Arg, <<"does not match">>})
+ end;
+convert_type({binary, Re, ReOpt}, Arg, Opt, Eos) ->
+ case re:run(Arg, Re, ReOpt) of
+ match -> unicode:characters_to_binary(Arg);
+ {match, _} -> unicode:characters_to_binary(Arg);
+ _ -> throw({Eos#eos.commands, Opt, Arg, <<"does not match">>})
+ end;
+convert_type(float, Arg, Opt, Eos) ->
+ get_float(Arg, Opt, Eos);
+convert_type({float, Opts}, Arg, Opt, Eos) ->
+ minimax(get_float(Arg, Opt, Eos), Opts, Eos, Opt, Arg);
+convert_type(atom, Arg, Opt, Eos) ->
+ try list_to_existing_atom(Arg)
+ catch error:badarg ->
+ throw({Eos#eos.commands, Opt, Arg, <<"is not an existing atom">>})
+ end;
+convert_type({atom, unsafe}, Arg, _Opt, _Eos) ->
+ list_to_atom(Arg);
+convert_type({atom, Choices}, Arg, Opt, Eos) ->
+ try
+ Atom = list_to_existing_atom(Arg),
+ lists:member(Atom, Choices) orelse throw({Eos#eos.commands, Opt, Arg, <<"is not one of the choices">>}),
+ Atom
+ catch error:badarg ->
+ throw({Eos#eos.commands, Opt, Arg, <<"is not an existing atom">>})
+ end;
+convert_type({custom, Fun}, Arg, Opt, Eos) ->
+ try Fun(Arg)
+ catch error:badarg ->
+ throw({Eos#eos.commands, Opt, Arg, <<"failed faildation">>})
+ end.
+
+%% Given Var, and list of {min, X}, {max, Y}, ensure that
+%% value falls within defined limits.
+minimax(Var, [], _Eos, _Opt, _Orig) ->
+ Var;
+minimax(Var, [{min, Min} | _], Eos, Opt, Orig) when Var < Min ->
+ throw({Eos#eos.commands, Opt, Orig, <<"is less than accepted minimum">>});
+minimax(Var, [{max, Max} | _], Eos, Opt, Orig) when Var > Max ->
+ throw({Eos#eos.commands, Opt, Orig, <<"is greater than accepted maximum">>});
+minimax(Var, [Num | Tail], Eos, Opt, Orig) when is_number(Num) ->
+ lists:member(Var, [Num|Tail]) orelse
+ throw({Eos#eos.commands, Opt, Orig, <<"is not one of the choices">>}),
+ Var;
+minimax(Var, [_ | Tail], Eos, Opt, Orig) ->
+ minimax(Var, Tail, Eos, Opt, Orig).
+
+%% returns integer from string, or errors out with debugging info
+get_int(Arg, Opt, Eos) ->
+ case string:to_integer(Arg) of
+ {Int, []} ->
+ Int;
+ _ ->
+ throw({Eos#eos.commands, Opt, Arg, <<"is not an integer">>})
+ end.
+
+%% returns float from string, that is floating-point, or integer
+get_float(Arg, Opt, Eos) ->
+ case string:to_float(Arg) of
+ {Float, []} ->
+ Float;
+ _ ->
+ %% possibly in disguise
+ case string:to_integer(Arg) of
+ {Int, []} ->
+ Int;
+ _ ->
+ throw({Eos#eos.commands, Opt, Arg, <<"is not a number">>})
+ end
+ end.
+
+%% Returns 'true' if String can be converted to a number
+is_digits(String) ->
+ case string:to_integer(String) of
+ {_Int, []} ->
+ true;
+ {_, _} ->
+ case string:to_float(String) of
+ {_Float, []} ->
+ true;
+ {_, _} ->
+ false
+ end
+ end.
+
+%% 'maybe' nargs for an option that does not have default set still have
+%% to produce something, let's call it hardcoded default.
+default(#{default := Default}) ->
+ Default;
+default(#{type := boolean}) ->
+ true;
+default(#{type := integer}) ->
+ 0;
+default(#{type := float}) ->
+ 0.0;
+default(#{type := string}) ->
+ "";
+default(#{type := binary}) ->
+ <<"">>;
+default(#{type := atom}) ->
+ undefined;
+%% no type given, consider it 'undefined' atom
+default(_) ->
+ undefined.
+
+%% command path is now in direct order
+format_path(Commands) ->
+ lists:join(" ", Commands).
+
+%%--------------------------------------------------------------------
+%% Validation and preprocessing
+%% Theoretically, Dialyzer should do that too.
+%% Practically, so many people ignore Dialyzer and then spend hours
+%% trying to understand why things don't work, that is makes sense
+%% to provide a mini-Dialyzer here.
+
+%% to simplify throwing errors with the right reason
+-define (INVALID(Kind, Entity, Path, Field, Text),
+ erlang:error({?MODULE, Kind, clean_path(Path), Field, Text}, [Entity], [{error_info, #{cause => #{}}}])).
+
+executable(#{progname := Prog}) when is_atom(Prog) ->
+ atom_to_list(Prog);
+executable(#{progname := Prog}) when is_binary(Prog) ->
+ binary_to_list(Prog);
+executable(#{progname := Prog}) ->
+ Prog;
+executable(_) ->
+ {ok, [[Prog]]} = init:get_argument(progname),
+ Prog.
+
+%% Recursive command validator
+validate_command([{Name, Cmd} | _] = Path, Prefixes) ->
+ (is_list(Name) andalso (not is_map_key(hd(Name), Prefixes))) orelse
+ ?INVALID(command, Cmd, tl(Path), commands,
+ <<"command name must be a string not starting with option prefix">>),
+ is_map(Cmd) orelse
+ ?INVALID(command, Cmd, Path, commands, <<"expected command()">>),
+ is_valid_command_help(maps:get(help, Cmd, [])) orelse
+ ?INVALID(command, Cmd, Path, help, <<"must be a printable unicode list, or a command help template">>),
+ is_map(maps:get(commands, Cmd, #{})) orelse
+ ?INVALID(command, Cmd, Path, commands, <<"expected map of #{string() => command()}">>),
+ case maps:get(handler, Cmd, optional) of
+ optional -> ok;
+ {Mod, ModFun} when is_atom(Mod), is_atom(ModFun) -> ok; %% map form
+ {Mod, ModFun, _} when is_atom(Mod), is_atom(ModFun) -> ok; %% positional form
+ {Fun, _} when is_function(Fun) -> ok; %% positional form
+ Fun when is_function(Fun, 1) -> ok;
+ _ -> ?INVALID(command, Cmd, Path, handler, <<"handler must be a valid callback, or an atom 'optional'">>)
+ end,
+ Cmd1 =
+ case maps:find(arguments, Cmd) of
+ error ->
+ Cmd;
+ {ok, Opts} when not is_list(Opts) ->
+ ?INVALID(command, Cmd, Path, arguments, <<"expected a list, [argument()]">>);
+ {ok, Opts} ->
+ Cmd#{arguments => [validate_option(Path, Opt) || Opt <- Opts]}
+ end,
+ %% collect all short & long option identifiers - to figure out any conflicts
+ lists:foldl(
+ fun ({_, #{arguments := Opts}}, Acc) ->
+ lists:foldl(
+ fun (#{short := Short, name := OName} = Arg, {AllS, AllL}) ->
+ is_map_key(Short, AllS) andalso
+ ?INVALID(argument, Arg, Path, short,
+ "short conflicting with previously defined short for "
+ ++ atom_to_list(maps:get(Short, AllS))),
+ {AllS#{Short => OName}, AllL};
+ (#{long := Long, name := OName} = Arg, {AllS, AllL}) ->
+ is_map_key(Long, AllL) andalso
+ ?INVALID(argument, Arg, Path, long,
+ "long conflicting with previously defined long for "
+ ++ atom_to_list(maps:get(Long, AllL))),
+ {AllS, AllL#{Long => OName}};
+ (_, AccIn) ->
+ AccIn
+ end, Acc, Opts);
+ (_, Acc) ->
+ Acc
+ end, {#{}, #{}}, Path),
+ %% verify all sub-commands
+ case maps:find(commands, Cmd1) of
+ error ->
+ {Name, Cmd1};
+ {ok, Sub} ->
+ {Name, Cmd1#{commands => maps:map(
+ fun (K, V) ->
+ {K, Updated} = validate_command([{K, V} | Path], Prefixes),
+ Updated
+ end, Sub)}}
+ end.
+
+%% validates option spec
+validate_option(Path, #{name := Name} = Arg) when is_atom(Name); is_list(Name); is_binary(Name) ->
+ %% verify specific arguments
+ %% help: string, 'hidden', or a tuple of {string(), ...}
+ is_valid_option_help(maps:get(help, Arg, [])) orelse
+ ?INVALID(argument, Arg, Path, help, <<"must be a string or valid help template">>),
+ io_lib:printable_unicode_list(maps:get(long, Arg, [])) orelse
+ ?INVALID(argument, Arg, Path, long, <<"must be a printable string">>),
+ is_boolean(maps:get(required, Arg, true)) orelse
+ ?INVALID(argument, Arg, Path, required, <<"must be a boolean">>),
+ io_lib:printable_unicode_list([maps:get(short, Arg, $a)]) orelse
+ ?INVALID(argument, Arg, Path, short, <<"must be a printable character">>),
+ Opt1 = maybe_validate(action, Arg, fun validate_action/3, Path),
+ Opt2 = maybe_validate(type, Opt1, fun validate_type/3, Path),
+ maybe_validate(nargs, Opt2, fun validate_args/3, Path);
+validate_option(Path, Arg) ->
+ ?INVALID(argument, Arg, Path, name, <<"argument must be a map containing 'name' field">>).
+
+maybe_validate(Key, Map, Fun, Path) when is_map_key(Key, Map) ->
+ maps:put(Key, Fun(maps:get(Key, Map), Path, Map), Map);
+maybe_validate(_Key, Map, _Fun, _Path) ->
+ Map.
+
+%% validate action field
+validate_action(store, _Path, _Opt) ->
+ store;
+validate_action({store, Term}, _Path, _Opt) ->
+ {store, Term};
+validate_action(append, _Path, _Opt) ->
+ append;
+validate_action({append, Term}, _Path, _Opt) ->
+ {append, Term};
+validate_action(count, _Path, _Opt) ->
+ count;
+validate_action(extend, _Path, #{nargs := Nargs}) when
+ Nargs =:= list; Nargs =:= nonempty_list; Nargs =:= all; is_integer(Nargs) ->
+ extend;
+validate_action(extend, _Path, #{type := {custom, _}}) ->
+ extend;
+validate_action(extend, Path, Arg) ->
+ ?INVALID(argument, Arg, Path, action, <<"extend action works only with lists">>);
+validate_action(_Action, Path, Arg) ->
+ ?INVALID(argument, Arg, Path, action, <<"unsupported">>).
+
+%% validate type field
+validate_type(Simple, _Path, _Opt) when Simple =:= boolean; Simple =:= integer; Simple =:= float;
+ Simple =:= string; Simple =:= binary; Simple =:= atom; Simple =:= {atom, unsafe} ->
+ Simple;
+validate_type({custom, Fun}, _Path, _Opt) when is_function(Fun, 1) ->
+ {custom, Fun};
+validate_type({float, Opts}, Path, Arg) ->
+ [?INVALID(argument, Arg, Path, type, <<"invalid validator">>)
+ || {Kind, Val} <- Opts, (Kind =/= min andalso Kind =/= max) orelse (not is_float(Val))],
+ {float, Opts};
+validate_type({integer, Opts}, Path, Arg) ->
+ [?INVALID(argument, Arg, Path, type, <<"invalid validator">>)
+ || {Kind, Val} <- Opts, (Kind =/= min andalso Kind =/= max) orelse (not is_integer(Val))],
+ {integer, Opts};
+validate_type({atom, Choices} = Valid, Path, Arg) when is_list(Choices) ->
+ [?INVALID(argument, Arg, Path, type, <<"unsupported">>) || C <- Choices, not is_atom(C)],
+ Valid;
+validate_type({string, Re} = Valid, _Path, _Opt) when is_list(Re) ->
+ Valid;
+validate_type({string, Re, L} = Valid, _Path, _Opt) when is_list(Re), is_list(L) ->
+ Valid;
+validate_type({binary, Re} = Valid, _Path, _Opt) when is_binary(Re) ->
+ Valid;
+validate_type({binary, Choices} = Valid, _Path, _Opt) when is_list(Choices), is_binary(hd(Choices)) ->
+ Valid;
+validate_type({binary, Re, L} = Valid, _Path, _Opt) when is_binary(Re), is_list(L) ->
+ Valid;
+validate_type(_Type, Path, Arg) ->
+ ?INVALID(argument, Arg, Path, type, <<"unsupported">>).
+
+validate_args(N, _Path, _Opt) when is_integer(N), N >= 1 -> N;
+validate_args(Simple, _Path, _Opt) when Simple =:= all; Simple =:= list; Simple =:= 'maybe'; Simple =:= nonempty_list ->
+ Simple;
+validate_args({'maybe', Term}, _Path, _Opt) -> {'maybe', Term};
+validate_args(_Nargs, Path, Arg) ->
+ ?INVALID(argument, Arg, Path, nargs, <<"unsupported">>).
+
+%% used to throw an error - strips command component out of path
+clean_path(Path) ->
+ {Cmds, _} = lists:unzip(Path),
+ lists:reverse(Cmds).
+
+is_valid_option_help(hidden) ->
+ true;
+is_valid_option_help(Help) when is_list(Help); is_binary(Help) ->
+ true;
+is_valid_option_help({Short, Desc}) when is_list(Short) orelse is_binary(Short), is_list(Desc) ->
+ %% verify that Desc is a list of string/type/default
+ lists:all(fun(type) -> true;
+ (default) -> true;
+ (S) when is_list(S); is_binary(S) -> true;
+ (_) -> false
+ end, Desc);
+is_valid_option_help({Short, Desc}) when is_list(Short) orelse is_binary(Short), is_function(Desc, 0) ->
+ true;
+is_valid_option_help(_) ->
+ false.
+
+is_valid_command_help(hidden) ->
+ true;
+is_valid_command_help(Help) when is_binary(Help) ->
+ true;
+is_valid_command_help(Help) when is_list(Help) ->
+ %% allow printable lists
+ case io_lib:printable_unicode_list(Help) of
+ true ->
+ true;
+ false ->
+ %% ... or a command help template
+ lists:all(
+ fun (Atom) when Atom =:= usage; Atom =:= commands; Atom =:= arguments; Atom =:= options -> true;
+ (Bin) when is_binary(Bin) -> true;
+ (Str) -> io_lib:printable_unicode_list(Str)
+ end, Help)
+ end;
+is_valid_command_help(_) ->
+ false.
+
+%%--------------------------------------------------------------------
+%% Built-in Help formatter
+
+format_help({ProgName, Root}, Format) ->
+ Prefix = hd(maps:get(prefixes, Format, [$-])),
+ Nested = maps:get(command, Format, []),
+ %% descent into commands collecting all options on the way
+ {_CmdName, Cmd, AllArgs} = collect_options(ProgName, Root, Nested, []),
+ %% split arguments into Flags, Options, Positional, and create help lines
+ {_, Longest, Flags, Opts, Args, OptL, PosL} = lists:foldl(fun format_opt_help/2,
+ {Prefix, 0, "", [], [], [], []}, AllArgs),
+ %% collect and format sub-commands
+ Immediate = maps:get(commands, Cmd, #{}),
+ {Long, Subs} = maps:fold(
+ fun (_Name, #{help := hidden}, {Long, SubAcc}) ->
+ {Long, SubAcc};
+ (Name, Sub, {Long, SubAcc}) ->
+ Help = maps:get(help, Sub, ""),
+ {max(Long, string:length(Name)), [{Name, Help}|SubAcc]}
+ end, {Longest, []}, maps:iterator(Immediate, ordered)),
+ %% format sub-commands
+ ShortCmd0 =
+ case map_size(Immediate) of
+ 0 ->
+ [];
+ Small when Small < 4 ->
+ Keys = lists:sort(maps:keys(Immediate)),
+ ["{" ++ lists:append(lists:join("|", Keys)) ++ "}"];
+ _Largs ->
+ ["<command>"]
+ end,
+ %% was it nested command?
+ ShortCmd = if Nested =:= [] -> ShortCmd0; true -> [lists:append(lists:join(" ", Nested)) | ShortCmd0] end,
+ %% format flags
+ FlagsForm = if Flags =:= [] -> [];
+ true -> [unicode:characters_to_list(io_lib:format("[~tc~ts]", [Prefix, Flags]))]
+ end,
+ %% format extended view
+ %% usage line has hardcoded format for now
+ Usage = [ProgName, ShortCmd, FlagsForm, Opts, Args],
+ %% format usage according to help template
+ Template0 = maps:get(help, Root, ""),
+ %% when there is no help defined for the command, or help is a string,
+ %% use the default format (original argparse behaviour)
+ Template =
+ case Template0 =:= "" orelse io_lib:printable_unicode_list(Template0) of
+ true ->
+ %% classic/compatibility format
+ NL = [io_lib:nl()],
+ Template1 = ["Usage:" ++ NL, usage, NL],
+ Template2 = maybe_add("~n", Template0, Template0 ++ NL, Template1),
+ Template3 = maybe_add("~nSubcommands:~n", Subs, commands, Template2),
+ Template4 = maybe_add("~nArguments:~n", PosL, arguments, Template3),
+ maybe_add("~nOptional arguments:~n", OptL, options, Template4);
+ false ->
+ Template0
+ end,
+
+ %% produce formatted output, taking viewport width into account
+ Parts = #{usage => Usage, commands => {Long, Subs},
+ arguments => {Longest, PosL}, options => {Longest, OptL}},
+ Width = maps:get(columns, Format, 80), %% might also use io:columns() here
+ lists:append([format_width(maps:find(Part, Parts), Part, Width) || Part <- Template]).
+
+%% collects options on the Path, and returns found Command
+collect_options(CmdName, Command, [], Args) ->
+ {CmdName, Command, maps:get(arguments, Command, []) ++ Args};
+collect_options(CmdName, Command, [Cmd|Tail], Args) ->
+ Sub = maps:get(commands, Command),
+ SubCmd = maps:get(Cmd, Sub),
+ collect_options(CmdName ++ " " ++ Cmd, SubCmd, Tail, maps:get(arguments, Command, []) ++ Args).
+
+%% conditionally adds text and empty lines
+maybe_add(_ToAdd, [], _Element, Template) ->
+ Template;
+maybe_add(ToAdd, _List, Element, Template) ->
+ Template ++ [io_lib:format(ToAdd, []), Element].
+
+format_width(error, Part, Width) ->
+ wrap_text(Part, 0, Width);
+format_width({ok, [ProgName, ShortCmd, FlagsForm, Opts, Args]}, usage, Width) ->
+ %% make every separate command/option to be a "word", and then
+ %% wordwrap it indented by the ProgName length + 3
+ Words = ShortCmd ++ FlagsForm ++ Opts ++ Args,
+ if Words =:= [] -> io_lib:format(" ~ts", [ProgName]);
+ true ->
+ Indent = string:length(ProgName),
+ Wrapped = wordwrap(Words, Width - Indent, 0, [], []),
+ Pad = lists:append(lists:duplicate(Indent + 3, " ")),
+ ArgLines = lists:join([io_lib:nl() | Pad], Wrapped),
+ io_lib:format(" ~ts~ts", [ProgName, ArgLines])
+ end;
+format_width({ok, {Len, Texts}}, _Part, Width) ->
+ SubFormat = io_lib:format(" ~~-~bts ~~ts~n", [Len]),
+ [io_lib:format(SubFormat, [N, wrap_text(D, Len + 3, Width)]) || {N, D} <- lists:reverse(Texts)].
+
+wrap_text(Text, Indent, Width) ->
+ %% split text into separate lines (paragraphs)
+ NL = io_lib:nl(),
+ Lines = string:split(Text, NL, all),
+ %% wordwrap every paragraph
+ Paragraphs = lists:append([wrap_line(L, Width, Indent) || L <- Lines]),
+ Pad = lists:append(lists:duplicate(Indent, " ")),
+ lists:join([NL | Pad], Paragraphs).
+
+wrap_line([], _Width, _Indent) ->
+ [[]];
+wrap_line(Line, Width, Indent) ->
+ [First | Tail] = string:split(Line, " ", all),
+ wordwrap(Tail, Width - Indent, string:length(First), First, []).
+
+wordwrap([], _Max, _Len, [], Lines) ->
+ lists:reverse(Lines);
+wordwrap([], _Max, _Len, Line, Lines) ->
+ lists:reverse([Line | Lines]);
+wordwrap([Word | Tail], Max, Len, Line, Lines) ->
+ WordLen = string:length(Word),
+ case Len + 1 + WordLen > Max of
+ true ->
+ wordwrap(Tail, Max, WordLen, Word, [Line | Lines]);
+ false ->
+ wordwrap(Tail, Max, WordLen + 1 + Len, [Line, <<" ">>, Word], Lines)
+ end.
+
+%% create help line for every option, collecting together all flags, short options,
+%% long options, and positional arguments
+
+%% format optional argument
+format_opt_help(#{help := hidden}, Acc) ->
+ Acc;
+format_opt_help(Opt, {Prefix, Longest, Flags, Opts, Args, OptL, PosL}) when ?IS_OPTION(Opt) ->
+ Desc = format_description(Opt),
+ %% does it need an argument? look for nargs and action
+ RequiresArg = requires_argument(Opt),
+ %% long form always added to Opts
+ NonOption = maps:get(required, Opt, false) =:= true,
+ {Name0, MaybeOpt0} =
+ case maps:find(long, Opt) of
+ error ->
+ {"", []};
+ {ok, Long} when NonOption, RequiresArg ->
+ FN = [Prefix | Long],
+ {FN, [format_required(true, [FN, " "], Opt)]};
+ {ok, Long} when RequiresArg ->
+ FN = [Prefix | Long],
+ {FN, [format_required(false, [FN, " "], Opt)]};
+ {ok, Long} when NonOption ->
+ FN = [Prefix | Long],
+ {FN, [FN]};
+ {ok, Long} ->
+ FN = [Prefix | Long],
+ {FN, [io_lib:format("[~ts]", [FN])]}
+ end,
+ %% short may go to flags, or Opts
+ {Name, MaybeFlag, MaybeOpt1} =
+ case maps:find(short, Opt) of
+ error ->
+ {Name0, [], MaybeOpt0};
+ {ok, Short} when RequiresArg ->
+ SN = [Prefix, Short],
+ {maybe_concat(SN, Name0), [],
+ [format_required(NonOption, [SN, " "], Opt) | MaybeOpt0]};
+ {ok, Short} ->
+ {maybe_concat([Prefix, Short], Name0), [Short], MaybeOpt0}
+ end,
+ %% apply override for non-default usage (in form of {Quick, Advanced} tuple
+ MaybeOpt2 =
+ case maps:find(help, Opt) of
+ {ok, {Str, _}} ->
+ [Str];
+ _ ->
+ MaybeOpt1
+ end,
+ %% name length, capped at 24
+ NameLen = string:length(Name),
+ Capped = min(24, NameLen),
+ {Prefix, max(Capped, Longest), Flags ++ MaybeFlag, Opts ++ MaybeOpt2, Args, [{Name, Desc} | OptL], PosL};
+
+%% format positional argument
+format_opt_help(#{name := Name} = Opt, {Prefix, Longest, Flags, Opts, Args, OptL, PosL}) ->
+ Desc = format_description(Opt),
+ %% positional, hence required
+ LName = io_lib:format("~ts", [Name]),
+ LPos = case maps:find(help, Opt) of
+ {ok, {Str, _}} ->
+ Str;
+ _ ->
+ format_required(maps:get(required, Opt, true), "", Opt)
+ end,
+ {Prefix, max(Longest, string:length(LName)), Flags, Opts, Args ++ [LPos], OptL, [{LName, Desc} | PosL]}.
+
+%% custom format
+format_description(#{help := {_Short, Fun}}) when is_function(Fun, 0) ->
+ Fun();
+format_description(#{help := {_Short, Desc}} = Opt) ->
+ lists:map(
+ fun (type) ->
+ format_type(Opt);
+ (default) ->
+ format_default(Opt);
+ (String) ->
+ String
+ end, Desc
+ );
+%% default format: "desc", "desc (type)", "desc (default)", "desc (type, default)"
+format_description(#{name := Name} = Opt) ->
+ NameStr = maps:get(help, Opt, io_lib:format("~ts", [Name])),
+ case {NameStr, format_type(Opt), format_default(Opt)} of
+ {"", "", Type} -> Type;
+ {"", Default, ""} -> Default;
+ {Desc, "", ""} -> Desc;
+ {Desc, "", Default} -> [Desc, " (", Default, ")"];
+ {Desc, Type, ""} -> [Desc, " (", Type, ")"];
+ {"", Type, Default} -> [Type, ", ", Default];
+ {Desc, Type, Default} -> [Desc, " (", Type, ", ", Default, ")"]
+ end.
+
+%% option formatting helpers
+maybe_concat(No, []) -> No;
+maybe_concat(No, L) -> [No, ", ", L].
+
+format_required(true, Extra, #{name := Name} = Opt) ->
+ io_lib:format("~ts<~ts>~ts", [Extra, Name, format_nargs(Opt)]);
+format_required(false, Extra, #{name := Name} = Opt) ->
+ io_lib:format("[~ts<~ts>~ts]", [Extra, Name, format_nargs(Opt)]).
+
+format_nargs(#{nargs := Dots}) when Dots =:= list; Dots =:= all; Dots =:= nonempty_list ->
+ "...";
+format_nargs(_) ->
+ "".
+
+format_type(#{type := {integer, Choices}}) when is_list(Choices), is_integer(hd(Choices)) ->
+ io_lib:format("choice: ~s", [lists:join(", ", [integer_to_list(C) || C <- Choices])]);
+format_type(#{type := {float, Choices}}) when is_list(Choices), is_number(hd(Choices)) ->
+ io_lib:format("choice: ~s", [lists:join(", ", [io_lib:format("~g", [C]) || C <- Choices])]);
+format_type(#{type := {Num, Valid}}) when Num =:= integer; Num =:= float ->
+ case {proplists:get_value(min, Valid), proplists:get_value(max, Valid)} of
+ {undefined, undefined} ->
+ io_lib:format("~s", [format_type(#{type => Num})]);
+ {Min, undefined} ->
+ io_lib:format("~s >= ~tp", [format_type(#{type => Num}), Min]);
+ {undefined, Max} ->
+ io_lib:format("~s <= ~tp", [format_type(#{type => Num}), Max]);
+ {Min, Max} ->
+ io_lib:format("~tp <= ~s <= ~tp", [Min, format_type(#{type => Num}), Max])
+ end;
+format_type(#{type := {string, Re, _}}) when is_list(Re), not is_list(hd(Re)) ->
+ io_lib:format("string re: ~ts", [Re]);
+format_type(#{type := {string, Re}}) when is_list(Re), not is_list(hd(Re)) ->
+ io_lib:format("string re: ~ts", [Re]);
+format_type(#{type := {binary, Re}}) when is_binary(Re) ->
+ io_lib:format("binary re: ~ts", [Re]);
+format_type(#{type := {binary, Re, _}}) when is_binary(Re) ->
+ io_lib:format("binary re: ~ts", [Re]);
+format_type(#{type := {StrBin, Choices}}) when StrBin =:= string orelse StrBin =:= binary, is_list(Choices) ->
+ io_lib:format("choice: ~ts", [lists:join(", ", Choices)]);
+format_type(#{type := atom}) ->
+ "existing atom";
+format_type(#{type := {atom, unsafe}}) ->
+ "atom";
+format_type(#{type := {atom, Choices}}) ->
+ io_lib:format("choice: ~ts", [lists:join(", ", [atom_to_list(C) || C <- Choices])]);
+format_type(#{type := boolean}) ->
+ "";
+format_type(#{type := integer}) ->
+ "int";
+format_type(#{type := Type}) when is_atom(Type) ->
+ io_lib:format("~ts", [Type]);
+format_type(_Opt) ->
+ "".
+
+format_default(#{default := Def}) when is_list(Def); is_binary(Def); is_atom(Def) ->
+ io_lib:format("~ts", [Def]);
+format_default(#{default := Def}) ->
+ io_lib:format("~tp", [Def]);
+format_default(_) ->
+ "".
+
+%%--------------------------------------------------------------------
+%% Basic handler execution
+handle(CmdMap, ArgMap, Path, #{handler := {Mod, ModFun, Default}}) ->
+ ArgList = arg_map_to_arg_list(CmdMap, Path, ArgMap, Default),
+ %% if argument count may not match, better error can be produced
+ erlang:apply(Mod, ModFun, ArgList);
+handle(_CmdMap, ArgMap, _Path, #{handler := {Mod, ModFun}}) when is_atom(Mod), is_atom(ModFun) ->
+ Mod:ModFun(ArgMap);
+handle(CmdMap, ArgMap, Path, #{handler := {Fun, Default}}) when is_function(Fun) ->
+ ArgList = arg_map_to_arg_list(CmdMap, Path, ArgMap, Default),
+ %% if argument count may not match, better error can be produced
+ erlang:apply(Fun, ArgList);
+handle(_CmdMap, ArgMap, _Path, #{handler := Handler}) when is_function(Handler, 1) ->
+ Handler(ArgMap).
+
+%% Given command map, path to reach a specific command, and a parsed argument
+%% map, returns a list of arguments (effectively used to transform map-based
+%% callback handler into positional).
+arg_map_to_arg_list(Command, Path, ArgMap, Default) ->
+ AllArgs = collect_arguments(Command, Path, []),
+ [maps:get(Arg, ArgMap, Default) || #{name := Arg} <- AllArgs].
+
+%% recursively descend into Path, ignoring arguments with duplicate names
+collect_arguments(Command, [], Acc) ->
+ Acc ++ maps:get(arguments, Command, []);
+collect_arguments(Command, [H|Tail], Acc) ->
+ Args = maps:get(arguments, Command, []),
+ Next = maps:get(H, maps:get(commands, Command, H)),
+ collect_arguments(Next, Tail, Acc ++ Args).
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index f8d629c02c..55e53cad3d 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -669,6 +669,9 @@ start(File, Opts) ->
false, Opts)},
{redefined_builtin_type,
bool_option(warn_redefined_builtin_type, nowarn_redefined_builtin_type,
+ true, Opts)},
+ {singleton_typevar,
+ bool_option(warn_singleton_typevar, nowarn_singleton_typevar,
true, Opts)}
],
Enabled1 = [Category || {Category,true} <- Enabled0],
@@ -1796,14 +1799,14 @@ is_pattern_expr_1({integer,_Anno,_I}) -> true;
is_pattern_expr_1({float,_Anno,_F}) -> true;
is_pattern_expr_1({atom,_Anno,_A}) -> true;
is_pattern_expr_1({tuple,_Anno,Es}) ->
- all(fun is_pattern_expr/1, Es);
+ all(fun is_pattern_expr_1/1, Es);
is_pattern_expr_1({nil,_Anno}) -> true;
is_pattern_expr_1({cons,_Anno,H,T}) ->
is_pattern_expr_1(H) andalso is_pattern_expr_1(T);
is_pattern_expr_1({op,_Anno,Op,A}) ->
erl_internal:arith_op(Op, 1) andalso is_pattern_expr_1(A);
is_pattern_expr_1({op,_Anno,Op,A1,A2}) ->
- erl_internal:arith_op(Op, 2) andalso all(fun is_pattern_expr/1, [A1,A2]);
+ erl_internal:arith_op(Op, 2) andalso all(fun is_pattern_expr_1/1, [A1,A2]);
is_pattern_expr_1(_Other) -> false.
pattern_map(Ps, Vt0, Old, St0) ->
@@ -2931,6 +2934,16 @@ check_type(Types, St) ->
"_"++_ -> AccSt;
_ -> add_error(Anno, {singleton_typevar, Var}, AccSt)
end;
+ (Var, {seen_once_union, Anno}, AccSt) ->
+ case is_warn_enabled(singleton_typevar, AccSt) of
+ true ->
+ case atom_to_list(Var) of
+ "_"++_ -> AccSt;
+ _ -> add_warning(Anno, {singleton_typevar, Var}, AccSt)
+ end;
+ false ->
+ AccSt
+ end;
(_Var, seen_multiple, AccSt) ->
AccSt
end, St1, SeenVars).
@@ -2971,6 +2984,7 @@ check_type_2({var, A, Name}, SeenVars, St) ->
NewSeenVars =
case maps:find(Name, SeenVars) of
{ok, {seen_once, _}} -> maps:put(Name, seen_multiple, SeenVars);
+ {ok, {seen_once_union, _}} -> maps:put(Name, seen_multiple, SeenVars);
{ok, seen_multiple} -> SeenVars;
error -> maps:put(Name, {seen_once, A}, SeenVars)
end,
@@ -3022,16 +3036,30 @@ check_type_2({type, _A, Tag, Args}=_F, SeenVars, St) when Tag =:= product;
lists:foldl(fun(T, {AccSeenVars, AccSt}) ->
check_type_1(T, AccSeenVars, AccSt)
end, {SeenVars, St}, Args);
-check_type_2({type, _A, union, Args}=_F, SeenVars, St) ->
- lists:foldl(fun(T, {AccSeenVars, AccSt}) ->
- {SeenVars0, St0} = check_type_1(T, SeenVars, AccSt),
- UpdatedSeenVars = maps:merge_with(fun (_K, {seen_once, _}, {seen_once, _}=R) -> R;
- (_K, {seen_once, _}, Else) -> Else;
- (_K, Else, {seen_once, _}) -> Else;
- (_K, Else1, _Else2) -> Else1
- end, SeenVars0, AccSeenVars),
- {UpdatedSeenVars, St0}
- end, {SeenVars, St}, Args);
+check_type_2({type, _A, union, Args}=_F, SeenVars0, St) ->
+ lists:foldl(fun(T, {AccSeenVars0, AccSt}) ->
+ {SeenVars1, St0} = check_type_1(T, SeenVars0, AccSt),
+ AccSeenVars = maps:merge_with(
+ fun (K, {seen_once, Anno}, {seen_once, _}) ->
+ case SeenVars0 of
+ #{K := _} ->
+ %% Unused outside of this union.
+ {seen_once, Anno};
+ #{} ->
+ {seen_once_union, Anno}
+ end;
+ (_K, {seen_once, Anno}, {seen_once_union, _}) ->
+ {seen_once_union, Anno};
+ (_K, {seen_once_union, _}=R, {seen_once, _}) -> R;
+ (_K, {seen_once_union, _}=R, {seen_once_union, _}) -> R;
+ (_K, {seen_once_union, _}, Else) -> Else;
+ (_K, {seen_once, _}, Else) -> Else;
+ (_K, Else, {seen_once_union, _}) -> Else;
+ (_K, Else, {seen_once, _}) -> Else;
+ (_K, Else1, _Else2) -> Else1
+ end, AccSeenVars0, SeenVars1),
+ {AccSeenVars, St0}
+ end, {SeenVars0, St}, Args);
check_type_2({type, Anno, TypeName, Args}, SeenVars, St) ->
#lint{module = Module, types=Types} = St,
Arity = length(Args),
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 45b6d633f5..5bc0704b68 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -37,6 +37,8 @@ obsolete(crypto, crypto_dyn_iv_update, 3) ->
{deprecated, "see the documentation for details", "OTP 27"};
obsolete(crypto, rand_uniform, 2) ->
{deprecated, "use rand:uniform/1 instead"};
+obsolete(dbg, stop_clear, 0) ->
+ {deprecated, "use dbg:stop/0 instead", "OTP 27"};
obsolete(disk_log, inc_wrap_file, 1) ->
{deprecated, "use disk_log:next_file/1 instead", "OTP 28"};
obsolete(erlang, now, 0) ->
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index 1a95030fc7..9c0f3a5c43 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl
index 816fb85a48..dccc6dcf3a 100644
--- a/lib/stdlib/src/sets.erl
+++ b/lib/stdlib/src/sets.erl
@@ -466,23 +466,12 @@ fold_1(Fun, Acc, Iter) ->
Set1 :: set(Element),
Set2 :: set(Element).
filter(F, #{}=D) when is_function(F, 1)->
- maps:from_keys(filter_1(F, maps:iterator(D)), ?VALUE);
+ %% For this purpose, it is more efficient to use
+ %% maps:from_keys than a map comprehension.
+ maps:from_keys([K || K := _ <- D, F(K)], ?VALUE);
filter(F, #set{}=D) when is_function(F, 1)->
filter_set(F, D).
-filter_1(Fun, Iter) ->
- case maps:next(Iter) of
- {K, _, NextIter} ->
- case Fun(K) of
- true ->
- [K | filter_1(Fun, NextIter)];
- false ->
- filter_1(Fun, NextIter)
- end;
- none ->
- []
- end.
-
%% get_slot(Hashdb, Key) -> Slot.
%% Get the slot. First hash on the new range, if we hit a bucket
%% which has not been split use the unsplit buddy bucket.
diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src
index 69bff1511b..a71ad0a954 100644
--- a/lib/stdlib/src/stdlib.app.src
+++ b/lib/stdlib/src/stdlib.app.src
@@ -21,7 +21,8 @@
{application, stdlib,
[{description, "ERTS CXC 138 10"},
{vsn, "%VSN%"},
- {modules, [array,
+ {modules, [argparse,
+ array,
base64,
beam_lib,
binary,
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 0cb84fd3dc..13efc74d85 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -54,7 +54,9 @@
{<<"^4\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^4\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^4\\.2$">>,[restart_new_emulator]},
- {<<"^4\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
+ {<<"^4\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^4\\.3$">>,[restart_new_emulator]},
+ {<<"^4\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
[{<<"^3\\.13$">>,[restart_new_emulator]},
{<<"^3\\.13\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.13\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
@@ -81,4 +83,6 @@
{<<"^4\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^4\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^4\\.2$">>,[restart_new_emulator]},
- {<<"^4\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
+ {<<"^4\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^4\\.3$">>,[restart_new_emulator]},
+ {<<"^4\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 5d4ffcf86e..2597157004 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -7,6 +7,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES= \
array_SUITE \
+ argparse_SUITE \
base64_SUITE \
base64_property_test_SUITE \
beam_lib_SUITE \
diff --git a/lib/stdlib/test/argparse_SUITE.erl b/lib/stdlib/test/argparse_SUITE.erl
new file mode 100644
index 0000000000..fb7eaecda1
--- /dev/null
+++ b/lib/stdlib/test/argparse_SUITE.erl
@@ -0,0 +1,1063 @@
+%%
+%%
+%% Copyright Maxim Fedorov
+%%
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+
+-module(argparse_SUITE).
+-author("maximfca@gmail.com").
+
+-export([suite/0, all/0, groups/0]).
+
+-export([
+ readme/0, readme/1,
+ basic/0, basic/1,
+ long_form_eq/0, long_form_eq/1,
+ built_in_types/0, built_in_types/1,
+ type_validators/0, type_validators/1,
+ invalid_arguments/0, invalid_arguments/1,
+ complex_command/0, complex_command/1,
+ unicode/0, unicode/1,
+ parser_error/0, parser_error/1,
+ nargs/0, nargs/1,
+ argparse/0, argparse/1,
+ negative/0, negative/1,
+ nodigits/0, nodigits/1,
+ pos_mixed_with_opt/0, pos_mixed_with_opt/1,
+ default_for_not_required/0, default_for_not_required/1,
+ global_default/0, global_default/1,
+ subcommand/0, subcommand/1,
+ very_short/0, very_short/1,
+ multi_short/0, multi_short/1,
+ proxy_arguments/0, proxy_arguments/1,
+
+ usage/0, usage/1,
+ usage_required_args/0, usage_required_args/1,
+ usage_template/0, usage_template/1,
+ parser_error_usage/0, parser_error_usage/1,
+ command_usage/0, command_usage/1,
+ usage_width/0, usage_width/1,
+
+ validator_exception/0, validator_exception/1,
+ validator_exception_format/0, validator_exception_format/1,
+
+ run_handle/0, run_handle/1
+]).
+
+-include_lib("stdlib/include/assert.hrl").
+
+suite() ->
+ [{timetrap, {seconds, 30}}].
+
+groups() ->
+ [
+ {parser, [parallel], [
+ readme, basic, long_form_eq, built_in_types, type_validators,
+ invalid_arguments, complex_command, unicode, parser_error,
+ nargs, argparse, negative, nodigits, pos_mixed_with_opt,
+ default_for_not_required, global_default, subcommand,
+ very_short, multi_short, proxy_arguments
+ ]},
+ {usage, [parallel], [
+ usage, usage_required_args, usage_template,
+ parser_error_usage, command_usage, usage_width
+ ]},
+ {validator, [parallel], [
+ validator_exception, validator_exception_format
+ ]},
+ {run, [parallel], [
+ run_handle
+ ]}
+ ].
+
+all() ->
+ [{group, parser}, {group, validator}, {group, usage}].
+
+%%--------------------------------------------------------------------
+%% Helpers
+
+prog() ->
+ {ok, [[ProgStr]]} = init:get_argument(progname), ProgStr.
+
+parser_error(CmdLine, CmdMap) ->
+ {error, Reason} = parse(CmdLine, CmdMap),
+ unicode:characters_to_list(argparse:format_error(Reason)).
+
+parse_opts(Args, Opts) ->
+ argparse:parse(string:lexemes(Args, " "), #{arguments => Opts}).
+
+parse(Args, Command) ->
+ argparse:parse(string:lexemes(Args, " "), Command).
+
+parse_cmd(Args, Command) ->
+ argparse:parse(string:lexemes(Args, " "), #{commands => Command}).
+
+%% ubiquitous command, containing sub-commands, and all possible option types
+%% with all nargs. Not all combinations though.
+ubiq_cmd() ->
+ #{
+ arguments => [
+ #{name => r, short => $r, type => boolean, help => "recursive"},
+ #{name => f, short => $f, type => boolean, long => "-force", help => "force"},
+ #{name => v, short => $v, type => boolean, action => count, help => "verbosity level"},
+ #{name => interval, short => $i, type => {integer, [{min, 1}]}, help => "interval set"},
+ #{name => weird, long => "-req", help => "required optional, right?"},
+ #{name => float, long => "-float", type => float, default => 3.14, help => "floating-point long form argument"}
+ ],
+ commands => #{
+ "start" => #{help => "verifies configuration and starts server",
+ arguments => [
+ #{name => server, help => "server to start"},
+ #{name => shard, short => $s, type => integer, nargs => nonempty_list, help => "initial shards"},
+ #{name => part, short => $p, type => integer, nargs => list, help => hidden},
+ #{name => z, short => $z, type => {integer, [{min, 1}, {max, 10}]}, help => "between"},
+ #{name => l, short => $l, type => {integer, [{max, 10}]}, nargs => 'maybe', help => "maybe lower"},
+ #{name => more, short => $m, type => {integer, [{max, 10}]}, help => "less than 10"},
+ #{name => optpos, required => false, type => {integer, []}, help => "optional positional"},
+ #{name => bin, short => $b, type => {binary, <<"m">>}, help => "binary with re"},
+ #{name => g, short => $g, type => {binary, <<"m">>, []}, help => "binary with re"},
+ #{name => t, short => $t, type => {string, "m"}, help => "string with re"},
+ #{name => e, long => "--maybe-req", required => true, type => integer, nargs => 'maybe', help => "maybe required int"},
+ #{name => y, required => true, long => "-yyy", short => $y, type => {string, "m", []}, help => "string with re"},
+ #{name => u, short => $u, type => {string, ["1", "2"]}, help => "string choices"},
+ #{name => choice, short => $c, type => {integer, [1,2,3]}, help => "tough choice"},
+ #{name => fc, short => $q, type => {float, [2.1,1.2]}, help => "floating choice"},
+ #{name => ac, short => $w, type => {atom, [one, two]}, help => "atom choice"},
+ #{name => au, long => "-unsafe", type => {atom, unsafe}, help => "unsafe atom"},
+ #{name => as, long => "-safe", type => atom, help => <<"safe atom">>},
+ #{name => name, required => false, nargs => list, help => hidden},
+ #{name => long, long => "foobar", required => false, help => [<<"foobaring option">>]}
+ ], commands => #{
+ "crawler" => #{arguments => [
+ #{name => extra, long => "--extra", help => "extra option very deep"}
+ ],
+ help => "controls crawler behaviour"},
+ "doze" => #{help => "dozes a bit"}}
+ },
+ "stop" => #{help => <<"stops running server">>, arguments => []
+ },
+ "status" => #{help => "prints server status", arguments => [],
+ commands => #{
+ "crawler" => #{
+ arguments => [#{name => extra, long => "--extra", help => "extra option very deep"}],
+ help => "crawler status"}}
+ },
+ "restart" => #{help => hidden, arguments => [
+ #{name => server, help => "server to restart"},
+ #{name => duo, short => $d, long => "-duo", help => "dual option"}
+ ]}
+ }
+ }.
+
+%%--------------------------------------------------------------------
+%% Parser Test Cases
+
+readme() ->
+ [{doc, "Test cases covered in the README"}].
+
+readme(Config) when is_list(Config) ->
+ Prog = prog(),
+ Rm = #{
+ arguments => [
+ #{name => dir},
+ #{name => force, short => $f, type => boolean, default => false},
+ #{name => recursive, short => $r, type => boolean}
+ ]
+ },
+ ?assertEqual({ok, #{dir => "dir", force => true, recursive => true}, [Prog], Rm},
+ argparse:parse(["-rf", "dir"], Rm)),
+ %% override progname
+ ?assertEqual("Usage:\n readme\n",
+ unicode:characters_to_list(argparse:help(#{}, #{progname => "readme"}))),
+ ?assertEqual("Usage:\n readme\n",
+ unicode:characters_to_list(argparse:help(#{}, #{progname => readme}))),
+ ?assertEqual("Usage:\n readme\n",
+ unicode:characters_to_list(argparse:help(#{}, #{progname => <<"readme">>}))),
+ %% test that command has priority over just a positional argument:
+ %% - parsing "opt sub" means "find positional argument "pos", then enter subcommand
+ %% - parsing "sub opt" means "enter sub-command, and then find positional argument"
+ Cmd = #{
+ commands => #{"sub" => #{}},
+ arguments => [#{name => pos}]
+ },
+ ?assertEqual(parse("opt sub", Cmd), parse("sub opt", Cmd)).
+
+basic() ->
+ [{doc, "Basic cases"}].
+
+basic(Config) when is_list(Config) ->
+ Prog = prog(),
+ %% empty command, with full options path
+ ?assertMatch({ok, #{}, [Prog, "cmd"], #{}},
+ argparse:parse(["cmd"], #{commands => #{"cmd" => #{}}})),
+ %% sub-command, with no path, but user-supplied argument
+ ?assertEqual({ok, #{}, [Prog, "cmd", "sub"], #{attr => pos}},
+ argparse:parse(["cmd", "sub"], #{commands => #{"cmd" => #{commands => #{"sub" => #{attr => pos}}}}})),
+ %% command with positional argument
+ PosCmd = #{arguments => [#{name => pos}]},
+ ?assertEqual({ok, #{pos => "arg"}, [Prog, "cmd"], PosCmd},
+ argparse:parse(["cmd", "arg"], #{commands => #{"cmd" => PosCmd}})),
+ %% command with optional argument
+ OptCmd = #{arguments => [#{name => force, short => $f, type => boolean}]},
+ ?assertEqual({ok, #{force => true}, [Prog, "rm"], OptCmd},
+ parse(["rm -f"], #{commands => #{"rm" => OptCmd}}), "rm -f"),
+ %% command with optional and positional argument
+ PosOptCmd = #{arguments => [#{name => force, short => $f, type => boolean}, #{name => dir}]},
+ ?assertEqual({ok, #{force => true, dir => "dir"}, [Prog, "rm"], PosOptCmd},
+ parse(["rm -f dir"], #{commands => #{"rm" => PosOptCmd}}), "rm -f dir"),
+ %% no command, just argument list
+ KernelCmd = #{arguments => [#{name => kernel, long => "kernel", type => atom, nargs => 2}]},
+ ?assertEqual({ok, #{kernel => [port, dist]}, [Prog], KernelCmd},
+ parse(["-kernel port dist"], KernelCmd)),
+ %% same but positional
+ ArgListCmd = #{arguments => [#{name => arg, nargs => 2, type => boolean}]},
+ ?assertEqual({ok, #{arg => [true, false]}, [Prog], ArgListCmd},
+ parse(["true false"], ArgListCmd)).
+
+long_form_eq() ->
+ [{doc, "Tests that long form supports --arg=value"}].
+
+long_form_eq(Config) when is_list(Config) ->
+ Prog = prog(),
+ %% cmd --arg=value
+ PosOptCmd = #{arguments => [#{name => arg, long => "-arg"}]},
+ ?assertEqual({ok, #{arg => "value"}, [Prog, "cmd"], PosOptCmd},
+ parse(["cmd --arg=value"], #{commands => #{"cmd" => PosOptCmd}})),
+ %% --integer=10
+ ?assertMatch({ok, #{int := 10}, _, _},
+ parse(["--int=10"], #{arguments => [#{name => int, type => integer, long => "-int"}]})).
+
+built_in_types() ->
+ [{doc, "Tests all built-in types supplied as a single argument"}].
+
+% built-in types testing
+built_in_types(Config) when is_list(Config) ->
+ Prog = [prog()],
+ Bool = #{arguments => [#{name => meta, type => boolean, short => $b, long => "-boolean"}]},
+ ?assertEqual({ok, #{}, Prog, Bool}, parse([""], Bool)),
+ ?assertEqual({ok, #{meta => true}, Prog, Bool}, parse(["-b"], Bool)),
+ ?assertEqual({ok, #{meta => true}, Prog, Bool}, parse(["--boolean"], Bool)),
+ ?assertEqual({ok, #{meta => false}, Prog, Bool}, parse(["--boolean false"], Bool)),
+ %% integer tests
+ Int = #{arguments => [#{name => int, type => integer, short => $i, long => "-int"}]},
+ ?assertEqual({ok, #{int => 1}, Prog, Int}, parse([" -i 1"], Int)),
+ ?assertEqual({ok, #{int => 1}, Prog, Int}, parse(["--int 1"], Int)),
+ ?assertEqual({ok, #{int => -1}, Prog, Int}, parse(["-i -1"], Int)),
+ %% floating point
+ Float = #{arguments => [#{name => f, type => float, short => $f}]},
+ ?assertEqual({ok, #{f => 44.44}, Prog, Float}, parse(["-f 44.44"], Float)),
+ %% atoms, existing
+ Atom = #{arguments => [#{name => atom, type => atom, short => $a, long => "-atom"}]},
+ ?assertEqual({ok, #{atom => atom}, Prog, Atom}, parse(["-a atom"], Atom)),
+ ?assertEqual({ok, #{atom => atom}, Prog, Atom}, parse(["--atom atom"], Atom)).
+
+type_validators() ->
+ [{doc, "Test that parser return expected conversions for valid arguments"}].
+
+type_validators(Config) when is_list(Config) ->
+ %% successful string regexes
+ ?assertMatch({ok, #{str := "me"}, _, _},
+ parse_opts("me", [#{name => str, type => {string, "m."}}])),
+ ?assertMatch({ok, #{str := "me"}, _, _},
+ parse_opts("me", [#{name => str, type => {string, "m.", []}}])),
+ ?assertMatch({ok, #{"str" := "me"}, _, _},
+ parse_opts("me", [#{name => "str", type => {string, "m.", [{capture, none}]}}])),
+ %% and binary too...
+ ?assertMatch({ok, #{bin := <<"me">>}, _, _},
+ parse_opts("me", [#{name => bin, type => {binary, <<"m.">>}}])),
+ ?assertMatch({ok, #{<<"bin">> := <<"me">>}, _, _},
+ parse_opts("me", [#{name => <<"bin">>, type => {binary, <<"m.">>, []}}])),
+ ?assertMatch({ok, #{bin := <<"me">>}, _, _},
+ parse_opts("me", [#{name => bin, type => {binary, <<"m.">>, [{capture, none}]}}])),
+ %% successful integer with range validators
+ ?assertMatch({ok, #{int := 5}, _, _},
+ parse_opts("5", [#{name => int, type => {integer, [{min, 0}, {max, 10}]}}])),
+ ?assertMatch({ok, #{bin := <<"5">>}, _, _},
+ parse_opts("5", [#{name => bin, type => binary}])),
+ ?assertMatch({ok, #{str := "011"}, _, _},
+ parse_opts("11", [#{name => str, type => {custom, fun(S) -> [$0|S] end}}])),
+ %% choices: valid
+ ?assertMatch({ok, #{bin := <<"K">>}, _, _},
+ parse_opts("K", [#{name => bin, type => {binary, [<<"M">>, <<"K">>]}}])),
+ ?assertMatch({ok, #{str := "K"}, _, _},
+ parse_opts("K", [#{name => str, type => {string, ["K", "N"]}}])),
+ ?assertMatch({ok, #{atom := one}, _, _},
+ parse_opts("one", [#{name => atom, type => {atom, [one, two]}}])),
+ ?assertMatch({ok, #{int := 12}, _, _},
+ parse_opts("12", [#{name => int, type => {integer, [10, 12]}}])),
+ ?assertMatch({ok, #{float := 1.3}, _, _},
+ parse_opts("1.3", [#{name => float, type => {float, [1.3, 1.4]}}])),
+ %% test for unsafe atom
+ %% ensure the atom does not exist
+ ?assertException(error, badarg, list_to_existing_atom("$can_never_be")),
+ {ok, ArgMap, _, _} = parse_opts("$can_never_be", [#{name => atom, type => {atom, unsafe}}]),
+ argparse:validate(#{arguments => [#{name => atom, type => {atom, unsafe}}]}),
+ %% now that atom exists, because argparse created it (in an unsafe way!)
+ ?assertEqual(list_to_existing_atom("$can_never_be"), maps:get(atom, ArgMap)),
+ %% test successful user-defined conversion
+ ?assertMatch({ok, #{user := "VER"}, _, _},
+ parse_opts("REV", [#{name => user, type => {custom, fun (Str) -> lists:reverse(Str) end}}])).
+
+invalid_arguments() ->
+ [{doc, "Test that parser return errors for invalid arguments"}].
+
+invalid_arguments(Config) when is_list(Config) ->
+ %% {float, [{min, float()} | {max, float()}]} |
+ Prog = [prog()],
+ MinFloat = #{name => float, type => {float, [{min, 1.0}]}},
+ ?assertEqual({error, {Prog, MinFloat, "0.0", <<"is less than accepted minimum">>}},
+ parse_opts("0.0", [MinFloat])),
+ MaxFloat = #{name => float, type => {float, [{max, 1.0}]}},
+ ?assertEqual({error, {Prog, MaxFloat, "2.0", <<"is greater than accepted maximum">>}},
+ parse_opts("2.0", [MaxFloat])),
+ %% {int, [{min, integer()} | {max, integer()}]} |
+ MinInt = #{name => int, type => {integer, [{min, 20}]}},
+ ?assertEqual({error, {Prog, MinInt, "10", <<"is less than accepted minimum">>}},
+ parse_opts("10", [MinInt])),
+ MaxInt = #{name => int, type => {integer, [{max, -10}]}},
+ ?assertEqual({error, {Prog, MaxInt, "-5", <<"is greater than accepted maximum">>}},
+ parse_opts("-5", [MaxInt])),
+ %% string: regex & regex with options
+ %% {string, string()} | {string, string(), []}
+ StrRegex = #{name => str, type => {string, "me.me"}},
+ ?assertEqual({error, {Prog, StrRegex, "me", <<"does not match">>}},
+ parse_opts("me", [StrRegex])),
+ StrRegexOpt = #{name => str, type => {string, "me.me", []}},
+ ?assertEqual({error, {Prog, StrRegexOpt, "me", <<"does not match">>}},
+ parse_opts("me", [StrRegexOpt])),
+ %% {binary, {re, binary()} | {re, binary(), []}
+ BinRegex = #{name => bin, type => {binary, <<"me.me">>}},
+ ?assertEqual({error, {Prog, BinRegex, "me", <<"does not match">>}},
+ parse_opts("me", [BinRegex])),
+ BinRegexOpt = #{name => bin, type => {binary, <<"me.me">>, []}},
+ ?assertEqual({error, {Prog, BinRegexOpt, "me", <<"does not match">>}},
+ parse_opts("me", [BinRegexOpt])),
+ %% invalid integer (comma , is not parsed)
+ ?assertEqual({error, {Prog, MinInt, "1,", <<"is not an integer">>}},
+ parse_opts(["1,"], [MinInt])),
+ %% test invalid choices
+ BinChoices = #{name => bin, type => {binary, [<<"M">>, <<"N">>]}},
+ ?assertEqual({error, {Prog, BinChoices, "K", <<"is not one of the choices">>}},
+ parse_opts("K", [BinChoices])),
+ StrChoices = #{name => str, type => {string, ["M", "N"]}},
+ ?assertEqual({error, {Prog, StrChoices, "K", <<"is not one of the choices">>}},
+ parse_opts("K", [StrChoices])),
+ AtomChoices = #{name => atom, type => {atom, [one, two]}},
+ ?assertEqual({error, {Prog, AtomChoices, "K", <<"is not one of the choices">>}},
+ parse_opts("K", [AtomChoices])),
+ IntChoices = #{name => int, type => {integer, [10, 11]}},
+ ?assertEqual({error, {Prog, IntChoices, "12", <<"is not one of the choices">>}},
+ parse_opts("12", [IntChoices])),
+ FloatChoices = #{name => float, type => {float, [1.2, 1.4]}},
+ ?assertEqual({error, {Prog, FloatChoices, "1.3", <<"is not one of the choices">>}},
+ parse_opts("1.3", [FloatChoices])),
+ %% unsuccessful user-defined conversion
+ ?assertMatch({error, {Prog, _, "REV", <<"failed faildation">>}},
+ parse_opts("REV", [#{name => user, type => {custom, fun (Str) -> integer_to_binary(Str) end}}])).
+
+complex_command() ->
+ [{doc, "Parses a complex command that has a mix of optional and positional arguments"}].
+
+complex_command(Config) when is_list(Config) ->
+ Command = #{arguments => [
+ %% options
+ #{name => string, short => $s, long => "-string", action => append, help => "String list option"},
+ #{name => boolean, type => boolean, short => $b, action => append, help => "Boolean list option"},
+ #{name => float, type => float, short => $f, long => "-float", action => append, help => "Float option"},
+ %% positional args
+ #{name => integer, type => integer, help => "Integer variable"},
+ #{name => string, help => "alias for string option", action => extend, nargs => list}
+ ]},
+ CmdMap = #{commands => #{"start" => Command}},
+ Parsed = argparse:parse(string:lexemes("start --float 1.04 -f 112 -b -b -s s1 42 --string s2 s3 s4", " "), CmdMap),
+ Expected = #{float => [1.04, 112], boolean => [true, true], integer => 42, string => ["s1", "s2", "s3", "s4"]},
+ ?assertEqual({ok, Expected, [prog(), "start"], Command}, Parsed).
+
+unicode() ->
+ [{doc, "Tests basic unicode support"}].
+
+unicode(Config) when is_list(Config) ->
+ %% test unicode short & long
+ ?assertMatch({ok, #{one := true}, _, _},
+ parse(["-Ф"], #{arguments => [#{name => one, short => $Ф, type => boolean}]})),
+ ?assertMatch({ok, #{long := true}, _, _},
+ parse(["--åäö"], #{arguments => [#{name => long, long => "-åäö", type => boolean}]})),
+ %% test default, help and value in unicode
+ Cmd = #{arguments => [#{name => text, type => binary, help => "åäö", default => <<"★"/utf8>>}]},
+ Expected = #{text => <<"★"/utf8>>},
+ Prog = [prog()],
+ ?assertEqual({ok, Expected, Prog, Cmd}, argparse:parse([], Cmd)), %% default
+ ?assertEqual({ok, Expected, Prog, Cmd}, argparse:parse(["★"], Cmd)), %% specified in the command line
+ ?assertEqual("Usage:\n " ++ prog() ++ " <text>\n\nArguments:\n text åäö (binary, ★)\n",
+ unicode:characters_to_list(argparse:help(Cmd))),
+ %% test command name and argument name in unicode
+ Uni = #{commands => #{"åäö" => #{help => "öФ"}}, handler => optional,
+ arguments => [#{name => "Ф", short => $ä, long => "åäö"}]},
+ UniExpected = "Usage:\n " ++ prog() ++
+ " {åäö} [-ä <Ф>] [-åäö <Ф>]\n\nSubcommands:\n åäö öФ\n\nOptional arguments:\n -ä, -åäö Ф\n",
+ ?assertEqual(UniExpected, unicode:characters_to_list(argparse:help(Uni))),
+ ParsedExpected = #{"Ф" => "öФ"},
+ ?assertEqual({ok, ParsedExpected, Prog, Uni}, argparse:parse(["-ä", "öФ"], Uni)).
+
+parser_error() ->
+ [{doc, "Tests error tuples that the parser returns"}].
+
+parser_error(Config) when is_list(Config) ->
+ Prog = prog(),
+ %% unknown option at the top of the path
+ ?assertEqual({error, {[Prog], undefined, "arg", <<>>}},
+ parse_cmd(["arg"], #{})),
+ %% positional argument missing in a sub-command
+ Opt = #{name => mode, required => true},
+ ?assertMatch({error, {[Prog, "start"], _, undefined, <<>>}},
+ parse_cmd(["start"], #{"start" => #{arguments => [Opt]}})),
+ %% optional argument missing in a sub-command
+ Opt1 = #{name => mode, short => $o, required => true},
+ ?assertMatch({error, {[Prog, "start"], _, undefined, <<>>}},
+ parse_cmd(["start"], #{"start" => #{arguments => [Opt1]}})),
+ %% positional argument: an atom that does not exist
+ Opt2 = #{name => atom, type => atom},
+ ?assertEqual({error, {[Prog], Opt2, "boo-foo", <<"is not an existing atom">>}},
+ parse_opts(["boo-foo"], [Opt2])),
+ %% optional argument missing some items
+ Opt3 = #{name => kernel, long => "kernel", type => atom, nargs => 2},
+ ?assertEqual({error, {[Prog], Opt3, ["port"], "expected 2, found 1 argument(s)"}},
+ parse_opts(["-kernel port"], [Opt3])),
+ %% positional argument missing some items
+ Opt4 = #{name => arg, type => atom, nargs => 3},
+ ?assertEqual({error, {[Prog], Opt4, ["p1"], "expected 3, found 1 argument(s)"}},
+ parse_opts(["p1"], [Opt4])),
+ %% short option with no argument, when it's needed
+ ?assertMatch({error, {_, _, undefined, <<"expected argument">>}},
+ parse("-1", #{arguments => [#{name => short49, short => 49}]})).
+
+nargs() ->
+ [{doc, "Tests argument consumption option, with nargs"}].
+
+nargs(Config) when is_list(Config) ->
+ Prog = [prog()],
+ %% consume optional list arguments
+ Opts = [
+ #{name => arg, short => $s, nargs => list, type => integer},
+ #{name => bool, short => $b, type => boolean}
+ ],
+ ?assertMatch({ok, #{arg := [1, 2, 3], bool := true}, _, _},
+ parse_opts(["-s 1 2 3 -b"], Opts)),
+ %% consume one_or_more arguments in an optional list
+ Opts2 = [
+ #{name => arg, short => $s, nargs => nonempty_list},
+ #{name => extra, short => $x}
+ ],
+ ?assertMatch({ok, #{extra := "X", arg := ["a","b","c"]}, _, _},
+ parse_opts(["-s port -s a b c -x X"], Opts2)),
+ %% error if there is no argument to consume
+ ?assertMatch({error, {_, _, ["-x"], <<"expected argument">>}},
+ parse_opts(["-s -x"], Opts2)),
+ %% error when positional has nargs = nonempty_list or pos_integer
+ ?assertMatch({error, {_, _, undefined, <<>>}},
+ parse_opts([""], [#{name => req, nargs => nonempty_list}])),
+ %% positional arguments consumption: one or more positional argument
+ OptsPos1 = #{arguments => [
+ #{name => arg, nargs => nonempty_list},
+ #{name => extra, short => $x}
+ ]},
+ ?assertEqual({ok, #{extra => "X", arg => ["b","c"]}, Prog, OptsPos1},
+ parse(["-x port -x a b c -x X"], OptsPos1)),
+ %% positional arguments consumption, any number (maybe zero)
+ OptsPos2 = #{arguments => [
+ #{name => arg, nargs => list},
+ #{name => extra, short => $x}
+ ]},
+ ?assertEqual({ok, #{extra => "X", arg => ["a","b","c"]}, Prog, OptsPos2},
+ parse(["-x port a b c -x X"], OptsPos2)),
+ %% positional: consume ALL arguments!
+ OptsAll = #{arguments => [
+ #{name => arg, nargs => all},
+ #{name => extra, short => $x}
+ ]},
+ ?assertEqual({ok, #{extra => "port", arg => ["a","b","c", "-x", "X"]}, Prog, OptsAll},
+ parse(["-x port a b c -x X"], OptsAll)),
+ %% maybe with a specified default
+ OptMaybe = [
+ #{name => foo, long => "-foo", nargs => {'maybe', c}, default => d},
+ #{name => bar, nargs => 'maybe', default => d}
+ ],
+ ?assertMatch({ok, #{foo := "YY", bar := "XX"}, Prog, _},
+ parse_opts(["XX --foo YY"], OptMaybe)),
+ ?assertMatch({ok, #{foo := c, bar := "XX"}, Prog, _},
+ parse_opts(["XX --foo"], OptMaybe)),
+ ?assertMatch({ok, #{foo := d, bar := d}, Prog, _},
+ parse_opts([""], OptMaybe)),
+ %% maybe with default provided by argparse
+ ?assertMatch({ok, #{foo := d, bar := "XX", baz := ok}, _, _},
+ parse_opts(["XX -b"], [#{name => baz, nargs => 'maybe', short => $b, default => ok} | OptMaybe])),
+ %% maybe arg - with no default given
+ ?assertMatch({ok, #{foo := d, bar := "XX", baz := 0}, _, _},
+ parse_opts(["XX -b"], [#{name => baz, nargs => 'maybe', short => $b, type => integer} | OptMaybe])),
+ ?assertMatch({ok, #{foo := d, bar := "XX", baz := ""}, _, _},
+ parse_opts(["XX -b"], [#{name => baz, nargs => 'maybe', short => $b, type => string} | OptMaybe])),
+ ?assertMatch({ok, #{foo := d, bar := "XX", baz := undefined}, _, _},
+ parse_opts(["XX -b"], [#{name => baz, nargs => 'maybe', short => $b, type => atom} | OptMaybe])),
+ ?assertMatch({ok, #{foo := d, bar := "XX", baz := <<"">>}, _, _},
+ parse_opts(["XX -b"], [#{name => baz, nargs => 'maybe', short => $b, type => binary} | OptMaybe])),
+ %% nargs: optional list, yet it still needs to be 'not required'!
+ OptList = [#{name => arg, nargs => list, required => false, type => integer}],
+ ?assertEqual({ok, #{}, Prog, #{arguments => OptList}}, parse_opts("", OptList)),
+ %% tests that action "count" with nargs "maybe" counts two times, first time
+ %% consuming an argument (for "maybe"), second time just counting
+ Cmd = #{arguments => [
+ #{name => short49, short => $1, long => "-force", action => count, nargs => 'maybe'}]},
+ ?assertEqual({ok, #{short49 => 2}, Prog, Cmd},
+ parse("-1 arg1 --force", Cmd)).
+
+argparse() ->
+ [{doc, "Tests success cases, inspired by argparse in Python"}].
+
+argparse(Config) when is_list(Config) ->
+ Prog = [prog()],
+ Parser = #{arguments => [
+ #{name => sum, long => "-sum", action => {store, sum}, default => max},
+ #{name => integers, type => integer, nargs => nonempty_list}
+ ]},
+ ?assertEqual({ok, #{integers => [1, 2, 3, 4], sum => max}, Prog, Parser},
+ parse("1 2 3 4", Parser)),
+ ?assertEqual({ok, #{integers => [1, 2, 3, 4], sum => sum}, Prog, Parser},
+ parse("1 2 3 4 --sum", Parser)),
+ ?assertEqual({ok, #{integers => [7, -1, 42], sum => sum}, Prog, Parser},
+ parse("--sum 7 -1 42", Parser)),
+ %% name or flags
+ Parser2 = #{arguments => [
+ #{name => bar, required => true},
+ #{name => foo, short => $f, long => "-foo"}
+ ]},
+ ?assertEqual({ok, #{bar => "BAR"}, Prog, Parser2}, parse("BAR", Parser2)),
+ ?assertEqual({ok, #{bar => "BAR", foo => "FOO"}, Prog, Parser2}, parse("BAR --foo FOO", Parser2)),
+ %PROG: error: the following arguments are required: bar
+ ?assertMatch({error, {Prog, _, undefined, <<>>}}, parse("--foo FOO", Parser2)),
+ %% action tests: default
+ ?assertMatch({ok, #{foo := "1"}, Prog, _},
+ parse("--foo 1", #{arguments => [#{name => foo, long => "-foo"}]})),
+ %% action test: store
+ ?assertMatch({ok, #{foo := 42}, Prog, _},
+ parse("--foo", #{arguments => [#{name => foo, long => "-foo", action => {store, 42}}]})),
+ %% action tests: boolean (variants)
+ ?assertMatch({ok, #{foo := true}, Prog, _},
+ parse("--foo", #{arguments => [#{name => foo, long => "-foo", action => {store, true}}]})),
+ ?assertMatch({ok, #{foo := 42}, Prog, _},
+ parse("--foo", #{arguments => [#{name => foo, long => "-foo", type => boolean, action => {store, 42}}]})),
+ ?assertMatch({ok, #{foo := true}, Prog, _},
+ parse("--foo", #{arguments => [#{name => foo, long => "-foo", type => boolean}]})),
+ ?assertMatch({ok, #{foo := true}, Prog, _},
+ parse("--foo true", #{arguments => [#{name => foo, long => "-foo", type => boolean}]})),
+ ?assertMatch({ok, #{foo := false}, Prog, _},
+ parse("--foo false", #{arguments => [#{name => foo, long => "-foo", type => boolean}]})),
+ %% action tests: append & append_const
+ ?assertMatch({ok, #{all := [1, "1"]}, Prog, _},
+ parse("--x 1 -x 1", #{arguments => [
+ #{name => all, long => "-x", type => integer, action => append},
+ #{name => all, short => $x, action => append}]})),
+ ?assertMatch({ok, #{all := ["Z", 2]}, Prog, _},
+ parse("--x -x", #{arguments => [
+ #{name => all, long => "-x", action => {append, "Z"}},
+ #{name => all, short => $x, action => {append, 2}}]})),
+ %% count:
+ ?assertMatch({ok, #{v := 3}, Prog, _},
+ parse("-v -v -v", #{arguments => [#{name => v, short => $v, action => count}]})).
+
+negative() ->
+ [{doc, "Test negative number parser"}].
+
+negative(Config) when is_list(Config) ->
+ Parser = #{arguments => [
+ #{name => x, short => $x, type => integer, action => store},
+ #{name => foo, nargs => 'maybe', required => false}
+ ]},
+ ?assertMatch({ok, #{x := -1}, _, _}, parse("-x -1", Parser)),
+ ?assertMatch({ok, #{x := -1, foo := "-5"}, _, _}, parse("-x -1 -5", Parser)),
+ %%
+ Parser2 = #{arguments => [
+ #{name => one, short => $1},
+ #{name => foo, nargs => 'maybe', required => false}
+ ]},
+
+ %% negative number options present, so -1 is an option
+ ?assertMatch({ok, #{one := "X"}, _, _}, parse("-1 X", Parser2)),
+ %% negative number options present, so -2 is an option
+ ?assertMatch({error, {_, undefined, "-2", _}}, parse("-2", Parser2)),
+
+ %% negative number options present, so both -1s are options
+ ?assertMatch({error, {_, _, undefined, _}}, parse("-1 -1", Parser2)),
+ %% no "-" prefix, can only be an integer
+ ?assertMatch({ok, #{foo := "-1"}, _, _}, argparse:parse(["-1"], Parser2, #{prefixes => "+"})),
+ %% no "-" prefix, can only be an integer, but just one integer!
+ ?assertMatch({error, {_, undefined, "-1", _}},
+ argparse:parse(["-2", "-1"], Parser2, #{prefixes => "+"})),
+ %% just in case, floats work that way too...
+ ?assertMatch({error, {_, undefined, "-2", _}},
+ parse("-2", #{arguments => [#{name => one, long => "1.2"}]})).
+
+nodigits() ->
+ [{doc, "Test prefixes and negative numbers together"}].
+
+nodigits(Config) when is_list(Config) ->
+ %% verify nodigits working as expected
+ Parser3 = #{arguments => [
+ #{name => extra, short => $3},
+ #{name => arg, nargs => list}
+ ]},
+ %% ensure not to consume optional prefix
+ ?assertEqual({ok, #{extra => "X", arg => ["a","b","3"]}, [prog()], Parser3},
+ argparse:parse(string:lexemes("-3 port a b 3 +3 X", " "), Parser3, #{prefixes => "-+"})).
+
+pos_mixed_with_opt() ->
+ [{doc, "Tests that optional argument correctly consumes expected argument"
+ "inspired by https://github.com/python/cpython/issues/59317"}].
+
+pos_mixed_with_opt(Config) when is_list(Config) ->
+ Parser = #{arguments => [
+ #{name => pos},
+ #{name => opt, default => 24, type => integer, long => "-opt"},
+ #{name => vars, nargs => list}
+ ]},
+ ?assertEqual({ok, #{pos => "1", opt => 8, vars => ["8", "9"]}, [prog()], Parser},
+ parse("1 2 --opt 8 8 9", Parser)).
+
+default_for_not_required() ->
+ [{doc, "Tests that default value is used for non-required positional argument"}].
+
+default_for_not_required(Config) when is_list(Config) ->
+ ?assertMatch({ok, #{def := 1}, _, _},
+ parse("", #{arguments => [#{name => def, short => $d, required => false, default => 1}]})),
+ ?assertMatch({ok, #{def := 1}, _, _},
+ parse("", #{arguments => [#{name => def, required => false, default => 1}]})).
+
+global_default() ->
+ [{doc, "Tests that a global default can be enabled for all non-required arguments"}].
+
+global_default(Config) when is_list(Config) ->
+ ?assertMatch({ok, #{def := "global"}, _, _},
+ argparse:parse("", #{arguments => [#{name => def, type => integer, required => false}]},
+ #{default => "global"})).
+
+subcommand() ->
+ [{doc, "Tests subcommands parser"}].
+
+subcommand(Config) when is_list(Config) ->
+ TwoCmd = #{arguments => [#{name => bar}]},
+ Cmd = #{
+ arguments => [#{name => force, type => boolean, short => $f}],
+ commands => #{"one" => #{
+ arguments => [#{name => foo, type => boolean, long => "-foo"}, #{name => baz}],
+ commands => #{
+ "two" => TwoCmd}}}},
+ ?assertEqual({ok, #{force => true, baz => "N1O1O", foo => true, bar => "bar"}, [prog(), "one", "two"], TwoCmd},
+ parse("one N1O1O -f two --foo bar", Cmd)),
+ %% it is an error not to choose subcommand
+ ?assertEqual({error, {[prog(), "one"], undefined, undefined, <<"subcommand expected">>}},
+ parse("one N1O1O -f", Cmd)).
+
+very_short() ->
+ [{doc, "Tests short option appended to the optional itself"}].
+
+very_short(Config) when is_list(Config) ->
+ ?assertMatch({ok, #{x := "V"}, _, _},
+ parse("-xV", #{arguments => [#{name => x, short => $x}]})).
+
+multi_short() ->
+ [{doc, "Tests multiple short arguments blend into one"}].
+
+multi_short(Config) when is_list(Config) ->
+ %% ensure non-flammable argument does not explode, even when it's possible
+ ?assertMatch({ok, #{v := "xv"}, _, _},
+ parse("-vxv", #{arguments => [#{name => v, short => $v}, #{name => x, short => $x}]})),
+ %% ensure 'verbosity' use-case works
+ ?assertMatch({ok, #{v := 3}, _, _},
+ parse("-vvv", #{arguments => [#{name => v, short => $v, action => count}]})),
+ %%
+ ?assertMatch({ok, #{recursive := true, force := true, path := "dir"}, _, _},
+ parse("-rf dir", #{arguments => [
+ #{name => recursive, short => $r, type => boolean},
+ #{name => force, short => $f, type => boolean},
+ #{name => path}
+ ]})).
+
+proxy_arguments() ->
+ [{doc, "Tests nargs => all used to proxy arguments to another script"}].
+
+proxy_arguments(Config) when is_list(Config) ->
+ Cmd = #{
+ commands => #{
+ "start" => #{
+ arguments => [
+ #{name => shell, short => $s, long => "-shell", type => boolean},
+ #{name => skip, short => $x, long => "-skip", type => boolean},
+ #{name => args, required => false, nargs => all}
+ ]
+ },
+ "stop" => #{},
+ "status" => #{
+ arguments => [
+ #{name => skip, required => false, default => "ok"},
+ #{name => args, required => false, nargs => all}
+ ]},
+ "state" => #{
+ arguments => [
+ #{name => skip, required => false},
+ #{name => args, required => false, nargs => all}
+ ]}
+ },
+ arguments => [
+ #{name => node}
+ ],
+ handler => fun (#{}) -> ok end
+ },
+ Prog = prog(),
+ ?assertMatch({ok, #{node := "node1"}, _, _}, parse("node1", Cmd)),
+ ?assertMatch({ok, #{node := "node1"}, [Prog, "stop"], #{}}, parse("node1 stop", Cmd)),
+ ?assertMatch({ok, #{node := "node2.org", shell := true, skip := true}, _, _}, parse("node2.org start -x -s", Cmd)),
+ ?assertMatch({ok, #{args := ["-app","key","value"],node := "node1.org"}, [Prog, "start"], _},
+ parse("node1.org start -app key value", Cmd)),
+ ?assertMatch({ok, #{args := ["-app","key","value", "-app2", "key2", "value2"],
+ node := "node3.org", shell := true}, [Prog, "start"], _},
+ parse("node3.org start -s -app key value -app2 key2 value2", Cmd)),
+ %% test that any non-required positionals are skipped
+ ?assertMatch({ok, #{args := ["-a","bcd"], node := "node2.org", skip := "ok"}, _, _}, parse("node2.org status -a bcd", Cmd)),
+ ?assertMatch({ok, #{args := ["-app", "key"], node := "node2.org"}, _, _}, parse("node2.org state -app key", Cmd)).
+
+%%--------------------------------------------------------------------
+%% Usage Test Cases
+
+usage() ->
+ [{doc, "Basic tests for help formatter, including 'hidden' help"}].
+
+usage(Config) when is_list(Config) ->
+ Cmd = ubiq_cmd(),
+ Usage = "Usage:\n erl start {crawler|doze} [-lrfv] [-s <shard>...] [-z <z>] [-m <more>] [-b <bin>]\n"
+ " [-g <g>] [-t <t>] ---maybe-req -y <y> --yyy <y> [-u <u>] [-c <choice>]\n"
+ " [-q <fc>] [-w <ac>] [--unsafe <au>] [--safe <as>] [-foobar <long>] [--force]\n"
+ " [-i <interval>] [--req <weird>] [--float <float>] <server> [<optpos>]\n\n"
+ "Subcommands:\n"
+ " crawler controls crawler behaviour\n"
+ " doze dozes a bit\n\n"
+ "Arguments:\n"
+ " server server to start\n"
+ " optpos optional positional (int)\n\n"
+ "Optional arguments:\n"
+ " -s initial shards (int)\n"
+ " -z between (1 <= int <= 10)\n"
+ " -l maybe lower (int <= 10)\n"
+ " -m less than 10 (int <= 10)\n"
+ " -b binary with re (binary re: m)\n"
+ " -g binary with re (binary re: m)\n"
+ " -t string with re (string re: m)\n"
+ " ---maybe-req maybe required int (int)\n"
+ " -y, --yyy string with re (string re: m)\n"
+ " -u string choices (choice: 1, 2)\n"
+ " -c tough choice (choice: 1, 2, 3)\n"
+ " -q floating choice (choice: 2.10000, 1.20000)\n"
+ " -w atom choice (choice: one, two)\n"
+ " --unsafe unsafe atom (atom)\n"
+ " --safe safe atom (existing atom)\n"
+ " -foobar foobaring option\n"
+ " -r recursive\n"
+ " -f, --force force\n"
+ " -v verbosity level\n"
+ " -i interval set (int >= 1)\n"
+ " --req required optional, right?\n"
+ " --float floating-point long form argument (float, 3.14)\n",
+ ?assertEqual(Usage, unicode:characters_to_list(argparse:help(Cmd,
+ #{progname => "erl", command => ["start"]}))),
+ FullCmd = "Usage:\n erl"
+ " <command> [-rfv] [--force] [-i <interval>] [--req <weird>] [--float <float>]\n\n"
+ "Subcommands:\n"
+ " start verifies configuration and starts server\n"
+ " status prints server status\n"
+ " stop stops running server\n\n"
+ "Optional arguments:\n"
+ " -r recursive\n"
+ " -f, --force force\n"
+ " -v verbosity level\n"
+ " -i interval set (int >= 1)\n"
+ " --req required optional, right?\n"
+ " --float floating-point long form argument (float, 3.14)\n",
+ ?assertEqual(FullCmd, unicode:characters_to_list(argparse:help(Cmd,
+ #{progname => erl}))),
+ CrawlerStatus = "Usage:\n erl status crawler [-rfv] [---extra <extra>] [--force] [-i <interval>]\n"
+ " [--req <weird>] [--float <float>]\n\nOptional arguments:\n"
+ " ---extra extra option very deep\n -r recursive\n"
+ " -f, --force force\n -v verbosity level\n"
+ " -i interval set (int >= 1)\n"
+ " --req required optional, right?\n"
+ " --float floating-point long form argument (float, 3.14)\n",
+ ?assertEqual(CrawlerStatus, unicode:characters_to_list(argparse:help(Cmd,
+ #{progname => "erl", command => ["status", "crawler"]}))),
+ ok.
+
+usage_required_args() ->
+ [{doc, "Verify that required args are printed as required in usage"}].
+
+usage_required_args(Config) when is_list(Config) ->
+ Cmd = #{commands => #{"test" => #{arguments => [#{name => required, required => true, long => "-req"}]}}},
+ Expected = "Usage:\n " ++ prog() ++ " test --req <required>\n\nOptional arguments:\n --req required\n",
+ ?assertEqual(Expected, unicode:characters_to_list(argparse:help(Cmd, #{command => ["test"]}))).
+
+usage_template() ->
+ [{doc, "Tests templates in help/usage"}].
+
+usage_template(Config) when is_list(Config) ->
+ %% Argument (positional)
+ Cmd = #{arguments => [#{
+ name => shard,
+ type => integer,
+ default => 0,
+ help => {"[-s SHARD]", ["initial number, ", type, <<" with a default value of ">>, default]}}
+ ]},
+ ?assertEqual("Usage:\n " ++ prog() ++ " [-s SHARD]\n\nArguments:\n shard initial number, int with a default value of 0\n",
+ unicode:characters_to_list(argparse:help(Cmd, #{}))),
+ %% Optional
+ Cmd1 = #{arguments => [#{
+ name => shard,
+ short => $s,
+ type => integer,
+ default => 0,
+ help => {<<"[-s SHARD]">>, ["initial number"]}}
+ ]},
+ ?assertEqual("Usage:\n " ++ prog() ++ " [-s SHARD]\n\nOptional arguments:\n -s initial number\n",
+ unicode:characters_to_list(argparse:help(Cmd1, #{}))),
+ %% ISO Date example
+ DefaultRange = {{2020, 1, 1}, {2020, 6, 22}},
+ CmdISO = #{
+ arguments => [
+ #{
+ name => range,
+ long => "-range",
+ short => $r,
+ help => {"[--range RNG]", fun() ->
+ {{FY, FM, FD}, {TY, TM, TD}} = DefaultRange,
+ lists:flatten(io_lib:format("date range, ~b-~b-~b..~b-~b-~b", [FY, FM, FD, TY, TM, TD]))
+ end},
+ type => {custom, fun(S) -> [S, DefaultRange] end},
+ default => DefaultRange
+ }
+ ]
+ },
+ ?assertEqual("Usage:\n " ++ prog() ++ " [--range RNG]\n\nOptional arguments:\n -r, --range date range, 2020-1-1..2020-6-22\n",
+ unicode:characters_to_list(argparse:help(CmdISO, #{}))),
+ ok.
+
+parser_error_usage() ->
+ [{doc, "Tests that parser errors have corresponding usage text"}].
+
+parser_error_usage(Config) when is_list(Config) ->
+ %% unknown arguments
+ Prog = prog(),
+ ?assertEqual(Prog ++ ": unknown argument: arg", parser_error(["arg"], #{})),
+ ?assertEqual(Prog ++ ": unknown argument: -a", parser_error(["-a"], #{})),
+ %% missing argument
+ ?assertEqual(Prog ++ ": required argument missing: need", parser_error([""],
+ #{arguments => [#{name => need}]})),
+ ?assertEqual(Prog ++ ": required argument missing: need", parser_error([""],
+ #{arguments => [#{name => need, short => $n, required => true}]})),
+ %% invalid value
+ ?assertEqual(Prog ++ ": invalid argument for need: foo is not an integer", parser_error(["foo"],
+ #{arguments => [#{name => need, type => integer}]})),
+ ?assertEqual(Prog ++ ": invalid argument for need: cAnNotExIsT is not an existing atom", parser_error(["cAnNotExIsT"],
+ #{arguments => [#{name => need, type => atom}]})).
+
+command_usage() ->
+ [{doc, "Test command help template"}].
+
+command_usage(Config) when is_list(Config) ->
+ Cmd = #{arguments => [
+ #{name => arg, help => "argument help"}, #{name => opt, short => $o, help => "option help"}],
+ help => ["Options:\n", options, arguments, <<"NOTAUSAGE">>, usage, "\n"]
+ },
+ ?assertEqual("Options:\n -o option help\n arg argument help\nNOTAUSAGE " ++ prog() ++ " [-o <opt>] <arg>\n",
+ unicode:characters_to_list(argparse:help(Cmd, #{}))).
+
+usage_width() ->
+ [{doc, "Test usage fitting in the viewport"}].
+
+usage_width(Config) when is_list(Config) ->
+ Cmd = #{arguments => [
+ #{name => arg, help => "argument help that spans way over allowed viewport width, wrapping words"},
+ #{name => opt, short => $o, long => "-option_long_name",
+ help => "another quite long word wrapped thing spanning over several lines"},
+ #{name => v, short => $v, type => boolean},
+ #{name => q, short => $q, type => boolean}],
+ commands => #{
+ "cmd1" => #{help => "Help for command number 1, not fitting at all"},
+ "cmd2" => #{help => <<"Short help">>},
+ "cmd3" => #{help => "Yet another instance of a very long help message"}
+ },
+ help => " Very long help line taking much more than 40 characters allowed by the test case.
+Also containing a few newlines.
+
+ Indented new lines must be honoured!"
+ },
+
+ Expected = "Usage:\n erl {cmd1|cmd2|cmd3} [-vq] [-o <opt>]\n"
+ " [--option_long_name <opt>] <arg>\n\n"
+ " Very long help line taking much more\n"
+ "than 40 characters allowed by the test\n"
+ "case.\n"
+ "Also containing a few newlines.\n\n"
+ " Indented new lines must be honoured!\n\n"
+ "Subcommands:\n"
+ " cmd1 Help for\n"
+ " command number\n"
+ " 1, not fitting\n"
+ " at all\n"
+ " cmd2 Short help\n"
+ " cmd3 Yet another\n"
+ " instance of a\n"
+ " very long help\n"
+ " message\n\n"
+ "Arguments:\n"
+ " arg argument help\n"
+ " that spans way\n"
+ " over allowed\n"
+ " viewport width,\n"
+ " wrapping words\n\n"
+ "Optional arguments:\n"
+ " -o, --option_long_name another quite\n"
+ " long word\n"
+ " wrapped thing\n"
+ " spanning over\n"
+ " several lines\n"
+ " -v v\n"
+ " -q q\n",
+
+ ?assertEqual(Expected, unicode:characters_to_list(argparse:help(Cmd, #{columns => 40, progname => "erl"}))).
+
+%%--------------------------------------------------------------------
+%% Validator Test Cases
+
+validator_exception() ->
+ [{doc, "Tests that the validator throws expected exceptions"}].
+
+validator_exception(Config) when is_list(Config) ->
+ Prg = [prog()],
+ %% conflicting option names
+ ?assertException(error, {argparse, argument, Prg, short, "short conflicting with previously defined short for one"},
+ argparse:validate(#{arguments => [#{name => one, short => $$}, #{name => two, short => $$}]})),
+ ?assertException(error, {argparse, argument, Prg, long, "long conflicting with previously defined long for one"},
+ argparse:validate(#{arguments => [#{name => one, long => "a"}, #{name => two, long => "a"}]})),
+ %% broken options
+ %% long must be a string
+ ?assertException(error, {argparse, argument, Prg, long, _},
+ argparse:validate(#{arguments => [#{name => one, long => ok}]})),
+ %% short must be a printable character
+ ?assertException(error, {argparse, argument, Prg, short, _},
+ argparse:validate(#{arguments => [#{name => one, short => ok}]})),
+ ?assertException(error, {argparse, argument, Prg, short, _},
+ argparse:validate(#{arguments => [#{name => one, short => 7}]})),
+ %% required is a boolean
+ ?assertException(error, {argparse, argument, Prg, required, _},
+ argparse:validate(#{arguments => [#{name => one, required => ok}]})),
+ ?assertException(error, {argparse, argument, Prg, help, _},
+ argparse:validate(#{arguments => [#{name => one, help => ok}]})),
+ %% broken commands
+ try argparse:help(#{}, #{progname => 123}), ?assert(false)
+ catch error:badarg:Stack ->
+ [{_, _, _, Ext} | _] = Stack,
+ #{cause := #{2 := Detail}} = proplists:get_value(error_info, Ext),
+ ?assertEqual(<<"progname is not valid">>, Detail)
+ end,
+ %% not-a-list of arguments provided to a subcommand
+ Prog = prog(),
+ ?assertException(error, {argparse, command, [Prog, "start"], arguments, <<"expected a list, [argument()]">>},
+ argparse:validate(#{commands => #{"start" => #{arguments => atom}}})),
+ %% command is not a map
+ ?assertException(error, {argparse, command, Prg, commands, <<"expected map of #{string() => command()}">>},
+ argparse:validate(#{commands => []})),
+ %% invalid commands field
+ ?assertException(error, {argparse, command, Prg, commands, _},
+ argparse:validate(#{commands => ok})),
+ ?assertException(error, {argparse, command, _, commands, _},
+ argparse:validate(#{commands => #{ok => #{}}})),
+ ?assertException(error, {argparse, command, _, help,
+ <<"must be a printable unicode list, or a command help template">>},
+ argparse:validate(#{commands => #{"ok" => #{help => ok}}})),
+ ?assertException(error, {argparse, command, _, handler, _},
+ argparse:validate(#{commands => #{"ok" => #{handler => fun validator_exception/0}}})),
+ %% extend + maybe: validator exception
+ ?assertException(error, {argparse, argument, _, action, <<"extend action works only with lists">>},
+ parse("-1 -1", #{arguments =>
+ [#{action => extend, name => short49, nargs => 'maybe', short => 49}]})).
+
+validator_exception_format() ->
+ [{doc, "Tests human-readable (EEP-54) format for exceptions thrown by the validator"}].
+
+validator_exception_format(Config) when is_list(Config) ->
+ %% set up as a contract: test that EEP-54 transformation is done (but don't check strings)
+ try
+ argparse:validate(#{commands => #{"one" => #{commands => #{"two" => atom}}}}),
+ ?assert(false)
+ catch
+ error:R1:S1 ->
+ #{1 := Cmd, reason := RR1, general := G} = argparse:format_error(R1, S1),
+ ?assertEqual("command specification is invalid", unicode:characters_to_list(G)),
+ ?assertEqual("command \"" ++ prog() ++ " one two\": invalid field 'commands', reason: expected command()",
+ unicode:characters_to_list(RR1)),
+ ?assertEqual(["atom"], Cmd)
+ end,
+ %% check argument
+ try
+ argparse:validate(#{arguments => [#{}]}),
+ ?assert(false)
+ catch
+ error:R2:S2 ->
+ #{1 := Cmd2, reason := RR2, general := G2} = argparse:format_error(R2, S2),
+ ?assertEqual("argument specification is invalid", unicode:characters_to_list(G2)),
+ ?assertEqual("command \"" ++ prog() ++
+ "\", argument '', invalid field 'name': argument must be a map containing 'name' field",
+ unicode:characters_to_list(RR2)),
+ ?assertEqual(["#{}"], Cmd2)
+ end.
+
+%%--------------------------------------------------------------------
+%% Validator Test Cases
+
+run_handle() ->
+ [{doc, "Very basic tests for argparse:run/3, choice of handlers formats"}].
+
+%% fun((arg_map()) -> term()) | %% handler accepting arg_map
+%% {module(), Fn :: atom()} | %% handler, accepting arg_map, Fn exported from module()
+%% {fun(() -> term()), term()} | %% handler, positional form (term() is supplied for omitted args)
+%% {module(), atom(), term()}
+
+run_handle(Config) when is_list(Config) ->
+ %% no subcommand, basic fun handler with argmap
+ ?assertEqual(6,
+ argparse:run(["-i", "3"], #{handler => fun (#{in := Val}) -> Val * 2 end,
+ arguments => [#{name => in, short => $i, type => integer}]}, #{})),
+ %% subcommand, positional fun() handler
+ ?assertEqual(6,
+ argparse:run(["mul", "2", "3"], #{commands => #{"mul" => #{
+ handler => {fun (match, L, R) -> L * R end, match},
+ arguments => [#{name => opt, short => $o},
+ #{name => l, type => integer}, #{name => r, type => integer}]}}},
+ #{})),
+ %% no subcommand, positional module-based function
+ ?assertEqual(6,
+ argparse:run(["2", "3"], #{handler => {erlang, '*', undefined},
+ arguments => [#{name => l, type => integer}, #{name => r, type => integer}]},
+ #{})),
+ %% subcommand, module-based function accepting argmap
+ ?assertEqual([{arg, "arg"}],
+ argparse:run(["map", "arg"], #{commands => #{"map" => #{
+ handler => {maps, to_list},
+ arguments => [#{name => arg}]}}},
+ #{})). \ No newline at end of file
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 834eb23335..81bc3e9a0d 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -907,105 +907,121 @@ unused_import(Config) when is_list(Config) ->
%% Test singleton type variables
singleton_type_var_errors(Config) when is_list(Config) ->
- Ts = [ {singleton_error1
- , <<"-spec test_singleton_typevars_in_union(Opts) -> term() when
+ Ts = [{singleton_error1,
+ <<"-spec test_singleton_typevars_in_union(Opts) -> term() when
Opts :: {ok, Unknown} | {error, Unknown}.
test_singleton_typevars_in_union(_) ->
error.
- ">>
- , []
- , { errors
- , [{{2,36},erl_lint,{singleton_typevar,'Unknown'}}]
- , []
- }
- }
- , { singleton_error2
- , <<"-spec test_singleton_list_typevars_in_union([Opts]) -> term() when
+ ">>,
+ [],
+ {warnings,[{{2,36},erl_lint,{singleton_typevar,'Unknown'}}]}},
+
+ {singleton_error2,
+ <<"-spec test_singleton_list_typevars_in_union([Opts]) -> term() when
Opts :: {ok, Unknown} | {error, Unknown}.
test_singleton_list_typevars_in_union(_) ->
- error.">>
- , []
- , { errors
- , [{{2,36},erl_lint,{singleton_typevar,'Unknown'}}]
- , []
- }
- }
- , { singleton_error3
- , <<"-spec test_singleton_list_typevars_in_list([Opts]) -> term() when
+ error.">>,
+ [],
+ {warnings,[{{2,36},erl_lint,{singleton_typevar,'Unknown'}}]}},
+
+ {singleton_error3,
+ <<"-spec test_singleton_list_typevars_in_list([Opts]) -> term() when
Opts :: {ok, Unknown}.
test_singleton_list_typevars_in_list(_) ->
- error.">>
- , []
- , { errors
- , [{{2,36},erl_lint,{singleton_typevar,'Unknown'}}]
- , []
- }
- }
- , { singleton_error4
- , <<"-spec test_singleton_list_typevars_in_list_with_type_subst([{ok, Unknown}]) -> term().
+ error.">>,
+ [],
+ {errors,
+ [{{2,36},erl_lint,{singleton_typevar,'Unknown'}}],[]}},
+
+ {singleton_error4,
+ <<"-spec test_singleton_list_typevars_in_list_with_type_subst([{ok, Unknown}]) -> term().
test_singleton_list_typevars_in_list_with_type_subst(_) ->
- error.">>
- , []
- , { errors
- , [{{1,86},erl_lint,{singleton_typevar,'Unknown'}}]
- , []
- }
- }
- , { singleton_error5
- , <<"-spec test_singleton_buried_typevars_in_union(Opts) -> term() when
+ error.">>,
+ [],
+ {errors,[{{1,86},erl_lint,{singleton_typevar,'Unknown'}}],[]}},
+
+ {singleton_error5,
+ <<"-spec test_singleton_buried_typevars_in_union(Opts) -> term() when
Opts :: {ok, Foo} | {error, Foo},
Foo :: {true, X} | {false, X}.
test_singleton_buried_typevars_in_union(_) ->
- error.">>
- , []
- , { errors
- , [{{3,38},erl_lint,{singleton_typevar,'X'}}]
- , []
- }
- }
- , { singleton_error6
- , <<"-spec test_multiple_subtypes_to_same_typevar(Opts) -> term() when
+ error.">>,
+ [],
+ {warnings,[{{3,38},erl_lint,{singleton_typevar,'X'}}]}},
+
+ {singleton_error6,
+ <<"-spec test_multiple_subtypes_to_same_typevar(Opts) -> term() when
Opts :: {Foo, Bar} | Y,
Foo :: X,
Bar :: X,
Y :: Z.
test_multiple_subtypes_to_same_typevar(_) ->
- error.">>
- , []
- , { errors
- , [{{5,31},erl_lint,{singleton_typevar,'Z'}}]
- , []
- }
- }
- , { singleton_error7
- , <<"-spec test_duplicate_non_terminal_var_in_union(Opts) -> term() when
+ error.">>,
+ [],
+ {errors,[{{5,31},erl_lint,{singleton_typevar,'Z'}}],[]}},
+
+ {singleton_error7,
+ <<"-spec test_duplicate_non_terminal_var_in_union(Opts) -> term() when
Opts :: {ok, U, U} | {error, U, U},
U :: Foo.
test_duplicate_non_terminal_var_in_union(_) ->
- error.">>
- , []
- , { errors
- , [{{3,31},erl_lint,{singleton_typevar,'Foo'}}]
- , []
- }
- }
- , { singleton_ok1
- , <<"-spec test_multiple_occurrences_singleton(Opts) -> term() when
+ error.">>,
+ [],
+ {errors,[{{3,31},erl_lint,{singleton_typevar,'Foo'}}],[]}},
+
+ {singleton_error8,
+ <<"-spec test_unused_outside_union(Opts) -> term() when
+ Unused :: Unknown,
+ A :: Unknown,
+ Opts :: {Unknown | A}.
+ test_unused_outside_union(_) ->
+ error.">>,
+ [],
+ {errors,[{{2,21},erl_lint,{singleton_typevar,'Unused'}}],[]}},
+
+ {singleton_disabled_warning,
+ <<"-spec test_singleton_typevars_in_union(Opts) -> term() when
+ Opts :: {ok, Unknown} | {error, Unknown}.
+ test_singleton_typevars_in_union(_) ->
+ error.
+ ">>,
+ [nowarn_singleton_typevar],
+ []},
+
+ {singleton_ok1,
+ <<"-spec test_multiple_occurrences_singleton(Opts) -> term() when
Opts :: {Foo, Foo}.
test_multiple_occurrences_singleton(_) ->
- ok.">>
- , []
- , []
- }
- , { singleton_ok2
- , <<"-spec id(X) -> X.
+ ok.">>,
+ [],
+ []},
+
+ {singleton_ok2,
+ <<"-spec id(X) -> X.
id(X) ->
- X.">>
- , []
- , []
- }
+ X.">>,
+ [],
+ []},
+
+ {singleton_ok3,
+ <<"-spec ok(Opts) -> term() when
+ Opts :: {Unknown, {ok, Unknown} | {error, Unknown}}.
+ ok(_) ->
+ error.">>,
+ [],
+ []},
+
+ {singleton_ok4,
+ <<"-spec ok(Opts) -> term() when
+ Union :: {ok, Unknown} | {error, Unknown},
+ Opts :: {{tag, Unknown} | Union}.
+ ok(_) ->
+ error.">>,
+ [],
+ []}
+
+ ],
- ],
[] = run(Config, Ts),
ok.
diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl
index 6bff254b0b..d99c7e9786 100644
--- a/lib/stdlib/test/gen_statem_SUITE.erl
+++ b/lib/stdlib/test/gen_statem_SUITE.erl
@@ -1409,7 +1409,7 @@ terminate_crash_format(Config) ->
terminate_crash_format(Config,format_status_statem,
{{formatted,idle},{formatted,crash_terminate}})
after
- dbg:stop_clear(),
+ dbg:stop(),
process_flag(trap_exit, OldFl),
error_logger_forwarder:unregister()
end.
diff --git a/lib/stdlib/test/property_test/uri_string_recompose.erl b/lib/stdlib/test/property_test/uri_string_recompose.erl
index 721f714c0f..4f37e4aa9c 100644
--- a/lib/stdlib/test/property_test/uri_string_recompose.erl
+++ b/lib/stdlib/test/property_test/uri_string_recompose.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index bc36c2acb7..a9cf48e997 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -2633,7 +2633,7 @@ order_of_children(_Config) ->
[{ok,[_]} = dbg:p(P,procs) || P <- Expected1],
terminate(Pid3, abnormal),
receive {exited,ExitedPids1} ->
- dbg:stop_clear(),
+ dbg:stop(),
case ExitedPids1 of
Expected1 -> ok;
_ -> ct:fail({faulty_termination_order,
@@ -2641,7 +2641,7 @@ order_of_children(_Config) ->
{got,ExitedPids1}})
end
after 3000 ->
- dbg:stop_clear(),
+ dbg:stop(),
ct:fail({shutdown_fail,timeout})
end,
@@ -2662,7 +2662,7 @@ order_of_children(_Config) ->
[{ok,[_]} = dbg:p(P,procs) || P <- Expected2],
exit(SupPid,shutdown),
receive {exited,ExitedPids2} ->
- dbg:stop_clear(),
+ dbg:stop(),
case ExitedPids2 of
Expected2 -> ok;
_ -> ct:fail({faulty_termination_order,
@@ -2670,7 +2670,7 @@ order_of_children(_Config) ->
{got,ExitedPids2}})
end
after 3000 ->
- dbg:stop_clear(),
+ dbg:stop(),
ct:fail({shutdown_fail,timeout})
end,
ok.
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index cd81d52182..d6706e69bf 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 4.3
+STDLIB_VSN = 4.3.1
diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl
index 2e0694c2cf..40f67b5660 100644
--- a/lib/syntax_tools/src/epp_dodger.erl
+++ b/lib/syntax_tools/src/epp_dodger.erl
@@ -517,6 +517,8 @@ quickscan_form([{'-', _Anno}, {'else', AnnoA} | _Ts]) ->
kill_form(AnnoA);
quickscan_form([{'-', _Anno}, {atom, AnnoA, endif} | _Ts]) ->
kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, feature} | _Ts]) ->
+ kill_form(AnnoA);
quickscan_form([{'-', Anno}, {'?', _}, {Type, _, _}=N | [{'(', _} | _]=Ts])
when Type =:= atom; Type =:= var ->
%% minus, macro and open parenthesis at start of form - assume that
diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl
index 978c78038d..8661df696d 100644
--- a/lib/tools/src/lcnt.erl
+++ b/lib/tools/src/lcnt.erl
@@ -893,7 +893,7 @@ clean_id_creation(Id) when is_port(Id) ->
<<131, PortTag, AtomTag>> = H,
LL = atomlen_bits(AtomTag),
CL = creation_bits(PortTag),
- <<L:LL, Node:L/binary, Ids:4/binary, _Creation/binary>> = Rest,
+ <<L:LL, Node:L/binary, Ids:8/binary, _Creation/binary>> = Rest,
Bin2 = list_to_binary([H, <<L:LL>>, Node, Ids, <<0:CL>>]),
binary_to_term(Bin2);
clean_id_creation(Id) ->
@@ -901,8 +901,7 @@ clean_id_creation(Id) ->
-define(PID_EXT, $g).
-define(NEW_PID_EXT, $X).
--define(PORT_EXT, $f).
--define(NEW_PORT_EXT, $Y).
+-define(V4_PORT_EXT, $x).
-define(ATOM_EXT, $d).
-define(SMALL_ATOM_EXT, $s).
-define(ATOM_UTF8_EXT, $v).
@@ -915,8 +914,7 @@ atomlen_bits(?SMALL_ATOM_UTF8_EXT) -> 8.
creation_bits(?PID_EXT) -> 8;
creation_bits(?NEW_PID_EXT) -> 32;
-creation_bits(?PORT_EXT) -> 8;
-creation_bits(?NEW_PORT_EXT) -> 32.
+creation_bits(?V4_PORT_EXT) -> 32.
%% serializer
diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl
index 09132d0f5b..5eeb7fa8b5 100644
--- a/lib/tools/src/xref_reader.erl
+++ b/lib/tools/src/xref_reader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/wx/api_gen/gl_gen.erl b/lib/wx/api_gen/gl_gen.erl
index 7a609158c7..eef715b83a 100644
--- a/lib/wx/api_gen/gl_gen.erl
+++ b/lib/wx/api_gen/gl_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -358,7 +358,10 @@ handle_arg_opt({c_only,Opt},P) -> P#arg{where=c, alt=Opt};
handle_arg_opt(list_binary, P) -> P#arg{alt=list_binary};
handle_arg_opt(string, P=#arg{type=T}) -> P#arg{type=T#type{base=string}};
handle_arg_opt({string,Max,Sz}, P=#arg{type=T}) ->
- P#arg{type=T#type{base=string, size={Max,Sz}}}.
+ P#arg{type=T#type{base=string, size={Max,Sz}}};
+handle_arg_opt({size, Sz}, P=#arg{type=T}) ->
+ P#arg{type=T#type{size={Sz,Sz}}}.
+
parse_type([], _Os) -> void;
parse_type(C, Os) ->
diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl
index b2c3ae2112..06fc6c9e58 100644
--- a/lib/wx/api_gen/gl_gen_erl.erl
+++ b/lib/wx/api_gen/gl_gen_erl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -88,8 +88,8 @@ gl_api(Fs, _GluNifs) ->
w("-on_load(init_nif/0).~n",[]),
w("~n-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]),
- w("-export([get_interface/0, rec/1, lookup_func/0]).\n",[]),
- w("-nifs([lookup_func/0]).\n",[]),
+ w("-export([get_interface/0, rec/1, lookup_func/1]).\n",[]),
+ w("-nifs([lookup_func_nif/1]).\n",[]),
w("-define(nif_stub,nif_stub_error(?LINE)).~n", []),
w("%% @hidden~n", []),
w("nif_stub_error(Line) ->~n"
@@ -118,7 +118,9 @@ gl_api(Fs, _GluNifs) ->
w(" error_logger:error_report([{gl, error}, {message, lists:flatten(Err)}]),~n", []),
w(" rec(Op)~n", []),
w(" end.~n~n", []),
- w("lookup_func() -> ?nif_stub.\n\n",[]),
+ w("lookup_func(functions) -> lookup_func_nif(1);\n",[]),
+ w("lookup_func(function_names) -> lookup_func_nif(2).\n\n",[]),
+ w("lookup_func_nif(_Func) -> ?nif_stub.\n\n",[]),
w("~n", []),
w("~n", []),
@@ -380,6 +382,8 @@ spec_arg_type2(T=#type{single={list, _Max}}) ->
"[" ++ spec_arg_type3(T) ++ "]";
spec_arg_type2(T=#type{single={list,_,_}}) ->
"[" ++ spec_arg_type3(T) ++ "]";
+spec_arg_type2(T=#type{single={list,_,_,_}}) ->
+ "[" ++ spec_arg_type3(T) ++ "]";
spec_arg_type2(T=#type{single={tuple_list,Sz}}) ->
"[{" ++ args(fun spec_arg_type3/1, ",", lists:duplicate(Sz,T)) ++ "}]".
diff --git a/lib/wx/api_gen/gl_gen_nif.erl b/lib/wx/api_gen/gl_gen_nif.erl
index cd8fdba7cd..a84bf454a5 100644
--- a/lib/wx/api_gen/gl_gen_nif.erl
+++ b/lib/wx/api_gen/gl_gen_nif.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -422,8 +422,8 @@ decode_var(P=#arg{name=Name, in=true, alt=Alt,
decode_var(P=#arg{name=Name, in=false,
- type=#type{name=T, base=Base, size=Szs}}, Argc)
- when Base =:= binary; Base =:= string ->
+ type=#type{name=T, base=Base, size=Szs, single=Single}}, Argc)
+ when not is_tuple(Single), (Base =:= binary orelse Base =:= string) ->
Sz = case Szs of
{Max,_} when is_integer(Max) -> integer_to_list(Max);
{Max,_} -> Max;
@@ -454,6 +454,19 @@ decode_var(P=#arg{name=Name, in=false, type=#type{name=T,single={list,Sz,_}}}, A
w(" std::vector <~s> ~s (~s);\n", [T, Name, Sz]),
w(" std::vector <ERL_NIF_TERM> ~s_ts (~s);\n", [Name, Sz]),
{P,Argc};
+decode_var(P=#arg{name=Name, in=false,
+ type=#type{base=Base, name=T,single={list,Sz,_,_}, size=Size}}, Argc) ->
+ case Base of
+ string ->
+ {BinSize, _} = Size,
+ w(" ~s = (unsigned char *) enif_alloc((int) ~s*sizeof(~s));\n", [Name,BinSize,T]),
+ w(" unsigned char *~s_ptr = ~s;\n", [Name,Name]),
+ store_free(Name ++ "_ptr");
+ _ ->
+ exit({?LINE, Base, P})
+ end,
+ w(" std::vector <ERL_NIF_TERM> ~s_ts (~s);\n", [Name, Sz]),
+ {P,Argc};
decode_var(P=#arg{name=Name, in=true, type=#type{name="GLUquadric"}}, Argc) ->
w(" if(!egl_get_ptr(env, argv[~w], (void **) &~s)) Badarg(~w,\"~s\");~n",
[Argc, Name,?OP,Name]),
@@ -576,10 +589,6 @@ build_ret(Name,_Q,#type{name=T,base=Base,size=Sz,single=true})
Ptr -> io_lib:format(" enif_make_uint64(env, (egl_uint64_t) ~s)", [Name]);
true -> io_lib:format(" enif_make_int64(env, (egl_int64_t) ~s)", [Name])
end;
-build_ret(Name,_Q,#type{base=string,single=true}) ->
- io_lib:format(" enif_make_string(env, (const char *) ~s, ERL_NIF_LATIN1)",[Name]);
-build_ret(Name,_Q,#type{base=string,size={_,_OutSz}}) ->
- io_lib:format(" enif_make_string(env, (const char *) ~s, ERL_NIF_LATIN1)",[Name]);
build_ret(Name,_Q,#type{name=_T,base=float,size=Sz,single=true}) ->
if Sz =< 4 -> io_lib:format(" enif_make_double(env, (double) ~s)", [Name]);
true -> io_lib:format(" enif_make_double(env, ~s)", [Name])
@@ -602,6 +611,12 @@ build_ret(Name,false,#type{single={list,Sz}}) when Sz >= 10, is_integer(Sz) ->
io_lib:format(" enif_make_list_from_array(env, ~s_ts, ~w)",[Name, Sz]);
build_ret(Name,false,#type{single={list,_,Sz}}) ->
io_lib:format(" enif_make_list_from_array(env, ~s_ts.data(), ~s)",[Name, Sz]);
+build_ret(Name,false,#type{single={list,_,Sz,_}}) ->
+ io_lib:format(" enif_make_list_from_array(env, ~s_ts.data(), ~s)",[Name, Sz]);
+build_ret(Name,_Q,#type{base=string,single=true}) ->
+ io_lib:format(" enif_make_string(env, (const char *) ~s, ERL_NIF_LATIN1)",[Name]);
+build_ret(Name,_Q,#type{base=string,size={_,_OutSz}}) ->
+ io_lib:format(" enif_make_string(env, (const char *) ~s, ERL_NIF_LATIN1)",[Name]);
build_ret(Name,_Q,T=#type{}) ->
io:format("{~p, {~p, {single,{tuple,X}}}}.~n", [get(current_func),Name]),
io:format(" ~p~n",[T]).
@@ -615,6 +630,12 @@ prepare_ret(#arg{name=Name, type=#type{single={list,_,Sz}}=T}) ->
Fetch = build_ret(Name ++ "[ri]", false, T#type{single=true}),
w(" for(int ri=0; ri < (int) ~s; ri++)\n"
" ~s_ts[ri] = ~s;\n",[Sz, Name, Fetch]);
+prepare_ret(#arg{name=Name, type=#type{single={list,_,Sz,Lengths}}=T}) ->
+ Fetch = build_ret(Name, false, T#type{single=true}),
+ w(" for(int ri=0; ri < (int) ~s; ri++) {\n"
+ " ~s_ts[ri] = ~s;\n",[Sz, Name, Fetch]),
+ w(" ~s += ~s[ri];\n"
+ " }\n", [Name, Lengths]);
prepare_ret(_) ->
ok.
diff --git a/lib/wx/api_gen/glapi.conf b/lib/wx/api_gen/glapi.conf
index e8304c31fe..b7b8ede1b7 100644
--- a/lib/wx/api_gen/glapi.conf
+++ b/lib/wx/api_gen/glapi.conf
@@ -483,24 +483,16 @@
{"glDebugMessageControl", [{"count", {c_only, {length, "ids"}}},
{"ids", {single, list}}]}.
-{"glDebugMessageInsertARB", {"length", {c_only, {size, "buf"}}}}.
-
-{"glGetDebugMessageLogARB", [{"sources", {single, {list, "count", "result"}}},
- {"types", {single, {list, "count", "result"}}},
- {"ids", {single, {list, "count", "result"}}},
- {"severities", {single, {list, "count", "result"}}},
- {"lengths", [{c_only, undefined}, {single, {list, "count", "result"}}]},
- {"messageLog", [{string, "bufSize", "result"}
- %%,{single, {list, "bufsize", "result"}}
- ]}]}.
+{"glDebugMessageInsert", {"length", {c_only, {size, "buf"}}}}.
{"glGetDebugMessageLog", [{"sources", {single, {list, "count", "result"}}},
{"types", {single, {list, "count", "result"}}},
{"ids", {single, {list, "count", "result"}}},
{"severities", {single, {list, "count", "result"}}},
{"lengths", [{c_only, undefined}, {single, {list, "count", "result"}}]},
- {"messageLog", [{string, "bufSize", "result"}
- %%,{single, {list, "bufsize", "result"}}
+ {"messageLog", [
+ {single, {list, "count", "result", "lengths"}},
+ {size, "bufSize"}
]}]}.
diff --git a/lib/wx/api_gen/wx_extra/added_func.h b/lib/wx/api_gen/wx_extra/added_func.h
index d3d8527976..bf18a16c6c 100644
--- a/lib/wx/api_gen/wx_extra/added_func.h
+++ b/lib/wx/api_gen/wx_extra/added_func.h
@@ -95,3 +95,9 @@ public:
void SetDragSource(wxAuiNotebook* s) { m_dragSource = s; }
wxAuiNotebook* GetDragSource() const { return m_dragSource; }
};
+
+class wxGLCanvas : public wxWindow
+{
+public:
+ bool CreateSurface();
+};
diff --git a/lib/wx/api_gen/wx_gen_nif.erl b/lib/wx/api_gen/wx_gen_nif.erl
index ab4850c6a9..e768f483fe 100644
--- a/lib/wx/api_gen/wx_gen_nif.erl
+++ b/lib/wx/api_gen/wx_gen_nif.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1460,7 +1460,9 @@ gen_macros() ->
w("#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE~n"),
w("#include <wx/msw/webview_ie.h>~n"),
w("#endif~n"),
-
+ w("#if wxUSE_GLCANVAS_EGL && !wxCHECK_VERSION(3,2,3)~n"),
+ w("#include <EGL/egl.h>~n"),
+ w("#endif~n"),
w("~n~n", []),
w("#ifndef wxICON_DEFAULT_BITMAP_TYPE~n",[]),
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index 5d0365da5d..be9529d40c 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -109,7 +109,10 @@
{'WXK_BROWSER', {test_if, "wxCHECK_VERSION(3,1,0)"}},
{'WXK_VOLUME', {test_if, "wxCHECK_VERSION(3,1,0)"}},
{'WXK_MEDIA', {test_if, "wxCHECK_VERSION(3,1,0)"}},
- {'WXK_LAUNCH', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WXK_LAUNCH', {test_if, "wxCHECK_VERSION(3,2,0)"}},
+
+ %% Varies in 3.1 and 3.2
+ wxDF_MAX,
{wxTOUCH, {test_if, "wxCHECK_VERSION(3,1,1)"}},
@@ -1439,11 +1442,23 @@
{pre_hook, [{erl, "{ok, _} = wxe_master:init_opengl(),"}]}
]},
{'SetCurrent', [{post_hook,[{c, "setActiveGL(memenv, Ecmd.caller, This, context)"}]}]},
+ {'CreateSurface', [{test_if, "wxUSE_GLCANVAS_EGL"},
+ {pre_hook,
+ [{c, %% Workaround for EGL and 3.2.* crashes
+ "\n#if !wxCHECK_VERSION(3,2,3)\n"
+ " if(!This) throw wxe_badarg(0);\n"
+ " if(This->GetEGLSurface() != EGL_NO_SURFACE)\n"
+ " eglDestroySurface(This->GetEGLDisplay(), This->GetEGLSurface());\n"
+ "#endif\n"
+ }]}
+ ]},
+ 'IsDisplaySupported',
'SwapBuffers']}.
{class, wxGLContext, object, [{ifdef, wxUSE_GLCANVAS}],
[{'wxGLContext', [{"ctxAttrs", nowhere}]},
- {'SetCurrent', [{post_hook,[{c, "setActiveGL(memenv, Ecmd.caller, win, This)"}]}]}
+ {'SetCurrent', [{post_hook,[{c, "setActiveGL(memenv, Ecmd.caller, win, This)"}]}]},
+ {'IsOK', [{test_if, "wxCHECK_VERSION(3,1,0)"}]}
]}.
{class, wxAuiManager, wxEvtHandler, [{ifdef, wxUSE_AUI}],
diff --git a/lib/wx/c_src/egl_impl.c b/lib/wx/c_src/egl_impl.c
index 7fe58a040d..868b32ab79 100644
--- a/lib/wx/c_src/egl_impl.c
+++ b/lib/wx/c_src/egl_impl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ ERL_NIF_TERM EGL_ATOM_BADARG;
static ErlNifFunc egl_funcs[] =
{
- {"lookup_func", 0, egl_lookup_func_func}
+ {"lookup_func_nif", 1, egl_lookup_func_func}
};
static int egl_init(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM arg)
{
@@ -142,9 +142,22 @@ void * egl_lookup_func(int op)
return gl_fns[op-GLE_LIB_START].nif_cb;
}
+const char * egl_lookup_func_desc(int op)
+{
+ return gl_fns[op-GLE_LIB_START].name;
+}
+
+
ERL_NIF_TERM egl_lookup_func_func(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- egl_uword func = (egl_uword) egl_lookup_func;
+ egl_uword func = 0;
+ unsigned int which;
+ if(!(enif_get_uint(env, argv[0], &which)) && !(which == 1 || which == 2))
+ return enif_make_badarg(env);
+ if(which == 1)
+ func = (egl_uword) egl_lookup_func;
+ if(which == 2)
+ func = (egl_uword) egl_lookup_func_desc;
if(sizeof(void *) == sizeof(unsigned int))
return enif_make_uint(env, (unsigned int) func);
else
diff --git a/lib/wx/c_src/gen/gl_nif.cpp b/lib/wx/c_src/gen/gl_nif.cpp
index 57e3196d98..efe09af3f7 100644
--- a/lib/wx/c_src/gen/gl_nif.cpp
+++ b/lib/wx/c_src/gen/gl_nif.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11518,15 +11518,13 @@ void ecb_glDebugMessageInsert(ErlNifEnv* env, ErlNifPid *self, ERL_NIF_TERM argv
GLenum type;
GLuint id;
GLenum severity;
- GLsizei length;
ErlNifBinary buf;
if(!enif_get_uint(env, argv[0], &source)) Badarg(5803,"source");
if(!enif_get_uint(env, argv[1], &type)) Badarg(5803,"type");
if(!enif_get_uint(env, argv[2], &id)) Badarg(5803,"id");
if(!enif_get_uint(env, argv[3], &severity)) Badarg(5803,"severity");
- if(!enif_get_int(env, argv[4], &length)) Badarg(5803,"length");
- if(!enif_inspect_binary(env, argv[5], &buf)) Badarg(5803,"buf");
- weglDebugMessageInsert(source,type,id,severity,length,(GLchar *) buf.data);
+ if(!enif_inspect_binary(env, argv[4], &buf)) Badarg(5803,"buf");
+ weglDebugMessageInsert(source,type,id,severity,(GLsizei) buf.size,(GLchar *) buf.data);
}
void ecb_glGetDebugMessageLog(ErlNifEnv* env, ErlNifPid *self, ERL_NIF_TERM argv[])
@@ -11549,6 +11547,8 @@ void ecb_glGetDebugMessageLog(ErlNifEnv* env, ErlNifPid *self, ERL_NIF_TERM argv
std::vector <GLsizei> lengths (count);
std::vector <ERL_NIF_TERM> lengths_ts (count);
messageLog = (unsigned char *) enif_alloc((int) bufSize*sizeof(GLchar));
+ unsigned char *messageLog_ptr = messageLog;
+ std::vector <ERL_NIF_TERM> messageLog_ts (count);
result = weglGetDebugMessageLog(count,bufSize,sources.data(),types.data(),ids.data(),severities.data(),lengths.data(),(GLchar *) messageLog);
for(int ri=0; ri < (int) result; ri++)
sources_ts[ri] = enif_make_int(env, sources[ri]);
@@ -11558,16 +11558,20 @@ void ecb_glGetDebugMessageLog(ErlNifEnv* env, ErlNifPid *self, ERL_NIF_TERM argv
ids_ts[ri] = enif_make_int(env, ids[ri]);
for(int ri=0; ri < (int) result; ri++)
severities_ts[ri] = enif_make_int(env, severities[ri]);
+ for(int ri=0; ri < (int) result; ri++) {
+ messageLog_ts[ri] = enif_make_string(env, (const char *) messageLog, ERL_NIF_LATIN1);
+ messageLog += lengths[ri];
+ }
reply = enif_make_tuple6(env,
enif_make_int(env, result),
enif_make_list_from_array(env, sources_ts.data(), result),
enif_make_list_from_array(env, types_ts.data(), result),
enif_make_list_from_array(env, ids_ts.data(), result),
enif_make_list_from_array(env, severities_ts.data(), result),
- enif_make_string(env, (const char *) messageLog, ERL_NIF_LATIN1) );
+ enif_make_list_from_array(env, messageLog_ts.data(), result) );
enif_send(NULL, self, env,
enif_make_tuple2(env, EGL_ATOM_REPLY, reply));
- enif_free(messageLog);
+ enif_free(messageLog_ptr);
}
void ecb_glPushDebugGroup(ErlNifEnv* env, ErlNifPid *self, ERL_NIF_TERM argv[])
diff --git a/lib/wx/c_src/gen/wxe_func_table.cpp b/lib/wx/c_src/gen/wxe_func_table.cpp
index 3a1d343c53..a044031472 100644
--- a/lib/wx/c_src/gen/wxe_func_table.cpp
+++ b/lib/wx/c_src/gen/wxe_func_table.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -2455,6 +2455,12 @@ extern void wxGLCanvas_new(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
#if wxUSE_GLCANVAS
extern void wxGLCanvas_SetCurrent(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
#endif // wxUSE_GLCANVAS
+#if wxUSE_GLCANVAS && wxUSE_GLCANVAS_EGL
+extern void wxGLCanvas_CreateSurface(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+#endif // wxUSE_GLCANVAS && wxUSE_GLCANVAS_EGL
+#if wxUSE_GLCANVAS
+extern void wxGLCanvas_IsDisplaySupported(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
extern void wxGLCanvas_SwapBuffers(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
#endif // wxUSE_GLCANVAS
@@ -2466,6 +2472,9 @@ extern void wxGLContext_new(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
#if wxUSE_GLCANVAS
extern void wxGLContext_SetCurrent(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
#endif // wxUSE_GLCANVAS
+#if wxUSE_GLCANVAS && wxCHECK_VERSION(3,1,0)
+extern void wxGLContext_IsOK(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+#endif // wxUSE_GLCANVAS && wxCHECK_VERSION(3,1,0)
#if wxUSE_GLCANVAS
#endif // wxUSE_GLCANVAS
#if wxUSE_AUI
@@ -7019,2085 +7028,2100 @@ wxe_fns_t wxe_fns[] =
#else
{NULL, "wxGLCanvas", "setCurrent", 0}, // 2494
#endif // wxUSE_GLCANVAS
+#if wxUSE_GLCANVAS && wxUSE_GLCANVAS_EGL
+ {wxGLCanvas_CreateSurface, "wxGLCanvas", "createSurface", 1}, // 2495
+#else
+ {NULL, "wxGLCanvas", "createSurface", 0}, // 2495
+#endif // wxUSE_GLCANVAS && wxUSE_GLCANVAS_EGL
#if wxUSE_GLCANVAS
- {wxGLCanvas_SwapBuffers, "wxGLCanvas", "swapBuffers", 1}, // 2495
+ {wxGLCanvas_IsDisplaySupported, "wxGLCanvas", "isDisplaySupported", 1}, // 2496
#else
- {NULL, "wxGLCanvas", "swapBuffers", 0}, // 2495
+ {NULL, "wxGLCanvas", "isDisplaySupported", 0}, // 2496
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {NULL, "wxGLCanvas", "'Destroy'", 1}, // 2496 obj destructor wxGLCanvas_destroy
+ {wxGLCanvas_SwapBuffers, "wxGLCanvas", "swapBuffers", 1}, // 2497
#else
- {NULL, "wxGLCanvas", "'Destroy'", 0}, // 2496
+ {NULL, "wxGLCanvas", "swapBuffers", 0}, // 2497
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {wxGLContext_new, "wxGLContext", "new", 2}, // 2497
+ {NULL, "wxGLCanvas", "'Destroy'", 1}, // 2498 obj destructor wxGLCanvas_destroy
#else
- {NULL, "wxGLContext", "new", 0}, // 2497
+ {NULL, "wxGLCanvas", "'Destroy'", 0}, // 2498
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {wxGLContext_SetCurrent, "wxGLContext", "setCurrent", 2}, // 2498
+ {wxGLContext_new, "wxGLContext", "new", 2}, // 2499
#else
- {NULL, "wxGLContext", "setCurrent", 0}, // 2498
+ {NULL, "wxGLContext", "new", 0}, // 2499
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {NULL, "wxGLContext", "'Destroy'", 1}, // 2499 obj destructor wxGLContext_destroy
+ {wxGLContext_SetCurrent, "wxGLContext", "setCurrent", 2}, // 2500
#else
- {NULL, "wxGLContext", "'Destroy'", 0}, // 2499
+ {NULL, "wxGLContext", "setCurrent", 0}, // 2500
+#endif // wxUSE_GLCANVAS
+#if wxUSE_GLCANVAS && wxCHECK_VERSION(3,1,0)
+ {wxGLContext_IsOK, "wxGLContext", "isOK", 1}, // 2501
+#else
+ {NULL, "wxGLContext", "isOK", 0}, // 2501
+#endif // wxUSE_GLCANVAS && wxCHECK_VERSION(3,1,0)
+#if wxUSE_GLCANVAS
+ {NULL, "wxGLContext", "'Destroy'", 1}, // 2502 obj destructor wxGLContext_destroy
+#else
+ {NULL, "wxGLContext", "'Destroy'", 0}, // 2502
#endif // wxUSE_GLCANVAS
#if wxUSE_AUI
- {wxAuiManager_new, "wxAuiManager", "new", 1}, // 2500
+ {wxAuiManager_new, "wxAuiManager", "new", 1}, // 2503
#else
- {NULL, "wxAuiManager", "new", 0}, // 2500
+ {NULL, "wxAuiManager", "new", 0}, // 2503
#endif // wxUSE_AUI
#if wxUSE_AUI
- {NULL, "wxAuiManager", "destroy", 1}, // 2501 obj destructor wxAuiManager_destruct
+ {NULL, "wxAuiManager", "destroy", 1}, // 2504 obj destructor wxAuiManager_destruct
#else
- {NULL, "wxAuiManager", "destroy", 0}, // 2501
+ {NULL, "wxAuiManager", "destroy", 0}, // 2504
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_AddPane_2_1, "wxAuiManager", "addPane", 3}, // 2502
+ {wxAuiManager_AddPane_2_1, "wxAuiManager", "addPane", 3}, // 2505
#else
- {NULL, "wxAuiManager", "addPane", 0}, // 2502
+ {NULL, "wxAuiManager", "addPane", 0}, // 2505
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_AddPane_2_0, "wxAuiManager", "addPane", 3}, // 2503
+ {wxAuiManager_AddPane_2_0, "wxAuiManager", "addPane", 3}, // 2506
#else
- {NULL, "wxAuiManager", "addPane", 0}, // 2503
+ {NULL, "wxAuiManager", "addPane", 0}, // 2506
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_AddPane_3, "wxAuiManager", "addPane", 4}, // 2504
+ {wxAuiManager_AddPane_3, "wxAuiManager", "addPane", 4}, // 2507
#else
- {NULL, "wxAuiManager", "addPane", 0}, // 2504
+ {NULL, "wxAuiManager", "addPane", 0}, // 2507
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_DetachPane, "wxAuiManager", "detachPane", 2}, // 2505
+ {wxAuiManager_DetachPane, "wxAuiManager", "detachPane", 2}, // 2508
#else
- {NULL, "wxAuiManager", "detachPane", 0}, // 2505
+ {NULL, "wxAuiManager", "detachPane", 0}, // 2508
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetAllPanes, "wxAuiManager", "getAllPanes", 1}, // 2506
+ {wxAuiManager_GetAllPanes, "wxAuiManager", "getAllPanes", 1}, // 2509
#else
- {NULL, "wxAuiManager", "getAllPanes", 0}, // 2506
+ {NULL, "wxAuiManager", "getAllPanes", 0}, // 2509
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetArtProvider, "wxAuiManager", "getArtProvider", 1}, // 2507
+ {wxAuiManager_GetArtProvider, "wxAuiManager", "getArtProvider", 1}, // 2510
#else
- {NULL, "wxAuiManager", "getArtProvider", 0}, // 2507
+ {NULL, "wxAuiManager", "getArtProvider", 0}, // 2510
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetDockSizeConstraint, "wxAuiManager", "getDockSizeConstraint", 1}, // 2508
+ {wxAuiManager_GetDockSizeConstraint, "wxAuiManager", "getDockSizeConstraint", 1}, // 2511
#else
- {NULL, "wxAuiManager", "getDockSizeConstraint", 0}, // 2508
+ {NULL, "wxAuiManager", "getDockSizeConstraint", 0}, // 2511
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetFlags, "wxAuiManager", "getFlags", 1}, // 2509
+ {wxAuiManager_GetFlags, "wxAuiManager", "getFlags", 1}, // 2512
#else
- {NULL, "wxAuiManager", "getFlags", 0}, // 2509
+ {NULL, "wxAuiManager", "getFlags", 0}, // 2512
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetManagedWindow, "wxAuiManager", "getManagedWindow", 1}, // 2510
+ {wxAuiManager_GetManagedWindow, "wxAuiManager", "getManagedWindow", 1}, // 2513
#else
- {NULL, "wxAuiManager", "getManagedWindow", 0}, // 2510
+ {NULL, "wxAuiManager", "getManagedWindow", 0}, // 2513
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetManager, "wxAuiManager", "getManager", 1}, // 2511
+ {wxAuiManager_GetManager, "wxAuiManager", "getManager", 1}, // 2514
#else
- {NULL, "wxAuiManager", "getManager", 0}, // 2511
+ {NULL, "wxAuiManager", "getManager", 0}, // 2514
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetPane_1_1, "wxAuiManager", "getPane", 2}, // 2512
+ {wxAuiManager_GetPane_1_1, "wxAuiManager", "getPane", 2}, // 2515
#else
- {NULL, "wxAuiManager", "getPane", 0}, // 2512
+ {NULL, "wxAuiManager", "getPane", 0}, // 2515
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetPane_1_0, "wxAuiManager", "getPane", 2}, // 2513
+ {wxAuiManager_GetPane_1_0, "wxAuiManager", "getPane", 2}, // 2516
#else
- {NULL, "wxAuiManager", "getPane", 0}, // 2513
+ {NULL, "wxAuiManager", "getPane", 0}, // 2516
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_HideHint, "wxAuiManager", "hideHint", 1}, // 2514
+ {wxAuiManager_HideHint, "wxAuiManager", "hideHint", 1}, // 2517
#else
- {NULL, "wxAuiManager", "hideHint", 0}, // 2514
+ {NULL, "wxAuiManager", "hideHint", 0}, // 2517
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_InsertPane, "wxAuiManager", "insertPane", 4}, // 2515
+ {wxAuiManager_InsertPane, "wxAuiManager", "insertPane", 4}, // 2518
#else
- {NULL, "wxAuiManager", "insertPane", 0}, // 2515
+ {NULL, "wxAuiManager", "insertPane", 0}, // 2518
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_LoadPaneInfo, "wxAuiManager", "loadPaneInfo", 3}, // 2516
+ {wxAuiManager_LoadPaneInfo, "wxAuiManager", "loadPaneInfo", 3}, // 2519
#else
- {NULL, "wxAuiManager", "loadPaneInfo", 0}, // 2516
+ {NULL, "wxAuiManager", "loadPaneInfo", 0}, // 2519
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_LoadPerspective, "wxAuiManager", "loadPerspective", 3}, // 2517
+ {wxAuiManager_LoadPerspective, "wxAuiManager", "loadPerspective", 3}, // 2520
#else
- {NULL, "wxAuiManager", "loadPerspective", 0}, // 2517
+ {NULL, "wxAuiManager", "loadPerspective", 0}, // 2520
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SavePaneInfo, "wxAuiManager", "savePaneInfo", 2}, // 2518
+ {wxAuiManager_SavePaneInfo, "wxAuiManager", "savePaneInfo", 2}, // 2521
#else
- {NULL, "wxAuiManager", "savePaneInfo", 0}, // 2518
+ {NULL, "wxAuiManager", "savePaneInfo", 0}, // 2521
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SavePerspective, "wxAuiManager", "savePerspective", 1}, // 2519
+ {wxAuiManager_SavePerspective, "wxAuiManager", "savePerspective", 1}, // 2522
#else
- {NULL, "wxAuiManager", "savePerspective", 0}, // 2519
+ {NULL, "wxAuiManager", "savePerspective", 0}, // 2522
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SetArtProvider, "wxAuiManager", "setArtProvider", 2}, // 2520
+ {wxAuiManager_SetArtProvider, "wxAuiManager", "setArtProvider", 2}, // 2523
#else
- {NULL, "wxAuiManager", "setArtProvider", 0}, // 2520
+ {NULL, "wxAuiManager", "setArtProvider", 0}, // 2523
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SetDockSizeConstraint, "wxAuiManager", "setDockSizeConstraint", 3}, // 2521
+ {wxAuiManager_SetDockSizeConstraint, "wxAuiManager", "setDockSizeConstraint", 3}, // 2524
#else
- {NULL, "wxAuiManager", "setDockSizeConstraint", 0}, // 2521
+ {NULL, "wxAuiManager", "setDockSizeConstraint", 0}, // 2524
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SetFlags, "wxAuiManager", "setFlags", 2}, // 2522
+ {wxAuiManager_SetFlags, "wxAuiManager", "setFlags", 2}, // 2525
#else
- {NULL, "wxAuiManager", "setFlags", 0}, // 2522
+ {NULL, "wxAuiManager", "setFlags", 0}, // 2525
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SetManagedWindow, "wxAuiManager", "setManagedWindow", 2}, // 2523
+ {wxAuiManager_SetManagedWindow, "wxAuiManager", "setManagedWindow", 2}, // 2526
#else
- {NULL, "wxAuiManager", "setManagedWindow", 0}, // 2523
+ {NULL, "wxAuiManager", "setManagedWindow", 0}, // 2526
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_ShowHint, "wxAuiManager", "showHint", 2}, // 2524
+ {wxAuiManager_ShowHint, "wxAuiManager", "showHint", 2}, // 2527
#else
- {NULL, "wxAuiManager", "showHint", 0}, // 2524
+ {NULL, "wxAuiManager", "showHint", 0}, // 2527
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_UnInit, "wxAuiManager", "unInit", 1}, // 2525
+ {wxAuiManager_UnInit, "wxAuiManager", "unInit", 1}, // 2528
#else
- {NULL, "wxAuiManager", "unInit", 0}, // 2525
+ {NULL, "wxAuiManager", "unInit", 0}, // 2528
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_Update, "wxAuiManager", "update", 1}, // 2526
+ {wxAuiManager_Update, "wxAuiManager", "update", 1}, // 2529
#else
- {NULL, "wxAuiManager", "update", 0}, // 2526
+ {NULL, "wxAuiManager", "update", 0}, // 2529
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_new_0, "wxAuiPaneInfo", "new", 0}, // 2527
+ {wxAuiPaneInfo_new_0, "wxAuiPaneInfo", "new", 0}, // 2530
#else
- {NULL, "wxAuiPaneInfo", "new", 0}, // 2527
+ {NULL, "wxAuiPaneInfo", "new", 0}, // 2530
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_new_1, "wxAuiPaneInfo", "new", 1}, // 2528
+ {wxAuiPaneInfo_new_1, "wxAuiPaneInfo", "new", 1}, // 2531
#else
- {NULL, "wxAuiPaneInfo", "new", 0}, // 2528
+ {NULL, "wxAuiPaneInfo", "new", 0}, // 2531
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_BestSize_1, "wxAuiPaneInfo", "bestSize", 2}, // 2529
+ {wxAuiPaneInfo_BestSize_1, "wxAuiPaneInfo", "bestSize", 2}, // 2532
#else
- {NULL, "wxAuiPaneInfo", "bestSize", 0}, // 2529
+ {NULL, "wxAuiPaneInfo", "bestSize", 0}, // 2532
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_BestSize_2, "wxAuiPaneInfo", "bestSize", 3}, // 2530
+ {wxAuiPaneInfo_BestSize_2, "wxAuiPaneInfo", "bestSize", 3}, // 2533
#else
- {NULL, "wxAuiPaneInfo", "bestSize", 0}, // 2530
+ {NULL, "wxAuiPaneInfo", "bestSize", 0}, // 2533
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Bottom, "wxAuiPaneInfo", "bottom", 1}, // 2531
+ {wxAuiPaneInfo_Bottom, "wxAuiPaneInfo", "bottom", 1}, // 2534
#else
- {NULL, "wxAuiPaneInfo", "bottom", 0}, // 2531
+ {NULL, "wxAuiPaneInfo", "bottom", 0}, // 2534
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_BottomDockable, "wxAuiPaneInfo", "bottomDockable", 2}, // 2532
+ {wxAuiPaneInfo_BottomDockable, "wxAuiPaneInfo", "bottomDockable", 2}, // 2535
#else
- {NULL, "wxAuiPaneInfo", "bottomDockable", 0}, // 2532
+ {NULL, "wxAuiPaneInfo", "bottomDockable", 0}, // 2535
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Caption, "wxAuiPaneInfo", "caption", 2}, // 2533
+ {wxAuiPaneInfo_Caption, "wxAuiPaneInfo", "caption", 2}, // 2536
#else
- {NULL, "wxAuiPaneInfo", "caption", 0}, // 2533
+ {NULL, "wxAuiPaneInfo", "caption", 0}, // 2536
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_CaptionVisible, "wxAuiPaneInfo", "captionVisible", 2}, // 2534
+ {wxAuiPaneInfo_CaptionVisible, "wxAuiPaneInfo", "captionVisible", 2}, // 2537
#else
- {NULL, "wxAuiPaneInfo", "captionVisible", 0}, // 2534
+ {NULL, "wxAuiPaneInfo", "captionVisible", 0}, // 2537
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Centre, "wxAuiPaneInfo", "centre", 1}, // 2535
+ {wxAuiPaneInfo_Centre, "wxAuiPaneInfo", "centre", 1}, // 2538
#else
- {NULL, "wxAuiPaneInfo", "centre", 0}, // 2535
+ {NULL, "wxAuiPaneInfo", "centre", 0}, // 2538
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_CentrePane, "wxAuiPaneInfo", "centrePane", 1}, // 2536
+ {wxAuiPaneInfo_CentrePane, "wxAuiPaneInfo", "centrePane", 1}, // 2539
#else
- {NULL, "wxAuiPaneInfo", "centrePane", 0}, // 2536
+ {NULL, "wxAuiPaneInfo", "centrePane", 0}, // 2539
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_CloseButton, "wxAuiPaneInfo", "closeButton", 2}, // 2537
+ {wxAuiPaneInfo_CloseButton, "wxAuiPaneInfo", "closeButton", 2}, // 2540
#else
- {NULL, "wxAuiPaneInfo", "closeButton", 0}, // 2537
+ {NULL, "wxAuiPaneInfo", "closeButton", 0}, // 2540
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_DefaultPane, "wxAuiPaneInfo", "defaultPane", 1}, // 2538
+ {wxAuiPaneInfo_DefaultPane, "wxAuiPaneInfo", "defaultPane", 1}, // 2541
#else
- {NULL, "wxAuiPaneInfo", "defaultPane", 0}, // 2538
+ {NULL, "wxAuiPaneInfo", "defaultPane", 0}, // 2541
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_DestroyOnClose, "wxAuiPaneInfo", "destroyOnClose", 2}, // 2539
+ {wxAuiPaneInfo_DestroyOnClose, "wxAuiPaneInfo", "destroyOnClose", 2}, // 2542
#else
- {NULL, "wxAuiPaneInfo", "destroyOnClose", 0}, // 2539
+ {NULL, "wxAuiPaneInfo", "destroyOnClose", 0}, // 2542
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Direction, "wxAuiPaneInfo", "direction", 2}, // 2540
+ {wxAuiPaneInfo_Direction, "wxAuiPaneInfo", "direction", 2}, // 2543
#else
- {NULL, "wxAuiPaneInfo", "direction", 0}, // 2540
+ {NULL, "wxAuiPaneInfo", "direction", 0}, // 2543
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Dock, "wxAuiPaneInfo", "dock", 1}, // 2541
+ {wxAuiPaneInfo_Dock, "wxAuiPaneInfo", "dock", 1}, // 2544
#else
- {NULL, "wxAuiPaneInfo", "dock", 0}, // 2541
+ {NULL, "wxAuiPaneInfo", "dock", 0}, // 2544
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Dockable, "wxAuiPaneInfo", "dockable", 2}, // 2542
+ {wxAuiPaneInfo_Dockable, "wxAuiPaneInfo", "dockable", 2}, // 2545
#else
- {NULL, "wxAuiPaneInfo", "dockable", 0}, // 2542
+ {NULL, "wxAuiPaneInfo", "dockable", 0}, // 2545
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Fixed, "wxAuiPaneInfo", "fixed", 1}, // 2543
+ {wxAuiPaneInfo_Fixed, "wxAuiPaneInfo", "fixed", 1}, // 2546
#else
- {NULL, "wxAuiPaneInfo", "fixed", 0}, // 2543
+ {NULL, "wxAuiPaneInfo", "fixed", 0}, // 2546
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Float, "wxAuiPaneInfo", "float", 1}, // 2544
+ {wxAuiPaneInfo_Float, "wxAuiPaneInfo", "float", 1}, // 2547
#else
- {NULL, "wxAuiPaneInfo", "float", 0}, // 2544
+ {NULL, "wxAuiPaneInfo", "float", 0}, // 2547
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Floatable, "wxAuiPaneInfo", "floatable", 2}, // 2545
+ {wxAuiPaneInfo_Floatable, "wxAuiPaneInfo", "floatable", 2}, // 2548
#else
- {NULL, "wxAuiPaneInfo", "floatable", 0}, // 2545
+ {NULL, "wxAuiPaneInfo", "floatable", 0}, // 2548
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_FloatingPosition_1, "wxAuiPaneInfo", "floatingPosition", 2}, // 2546
+ {wxAuiPaneInfo_FloatingPosition_1, "wxAuiPaneInfo", "floatingPosition", 2}, // 2549
#else
- {NULL, "wxAuiPaneInfo", "floatingPosition", 0}, // 2546
+ {NULL, "wxAuiPaneInfo", "floatingPosition", 0}, // 2549
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_FloatingPosition_2, "wxAuiPaneInfo", "floatingPosition", 3}, // 2547
+ {wxAuiPaneInfo_FloatingPosition_2, "wxAuiPaneInfo", "floatingPosition", 3}, // 2550
#else
- {NULL, "wxAuiPaneInfo", "floatingPosition", 0}, // 2547
+ {NULL, "wxAuiPaneInfo", "floatingPosition", 0}, // 2550
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_FloatingSize_1, "wxAuiPaneInfo", "floatingSize", 2}, // 2548
+ {wxAuiPaneInfo_FloatingSize_1, "wxAuiPaneInfo", "floatingSize", 2}, // 2551
#else
- {NULL, "wxAuiPaneInfo", "floatingSize", 0}, // 2548
+ {NULL, "wxAuiPaneInfo", "floatingSize", 0}, // 2551
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_FloatingSize_2, "wxAuiPaneInfo", "floatingSize", 3}, // 2549
+ {wxAuiPaneInfo_FloatingSize_2, "wxAuiPaneInfo", "floatingSize", 3}, // 2552
#else
- {NULL, "wxAuiPaneInfo", "floatingSize", 0}, // 2549
+ {NULL, "wxAuiPaneInfo", "floatingSize", 0}, // 2552
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Gripper, "wxAuiPaneInfo", "gripper", 2}, // 2550
+ {wxAuiPaneInfo_Gripper, "wxAuiPaneInfo", "gripper", 2}, // 2553
#else
- {NULL, "wxAuiPaneInfo", "gripper", 0}, // 2550
+ {NULL, "wxAuiPaneInfo", "gripper", 0}, // 2553
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GripperTop, "wxAuiPaneInfo", "gripperTop", 2}, // 2551
+ {wxAuiPaneInfo_GripperTop, "wxAuiPaneInfo", "gripperTop", 2}, // 2554
#else
- {NULL, "wxAuiPaneInfo", "gripperTop", 0}, // 2551
+ {NULL, "wxAuiPaneInfo", "gripperTop", 0}, // 2554
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasBorder, "wxAuiPaneInfo", "hasBorder", 1}, // 2552
+ {wxAuiPaneInfo_HasBorder, "wxAuiPaneInfo", "hasBorder", 1}, // 2555
#else
- {NULL, "wxAuiPaneInfo", "hasBorder", 0}, // 2552
+ {NULL, "wxAuiPaneInfo", "hasBorder", 0}, // 2555
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasCaption, "wxAuiPaneInfo", "hasCaption", 1}, // 2553
+ {wxAuiPaneInfo_HasCaption, "wxAuiPaneInfo", "hasCaption", 1}, // 2556
#else
- {NULL, "wxAuiPaneInfo", "hasCaption", 0}, // 2553
+ {NULL, "wxAuiPaneInfo", "hasCaption", 0}, // 2556
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasCloseButton, "wxAuiPaneInfo", "hasCloseButton", 1}, // 2554
+ {wxAuiPaneInfo_HasCloseButton, "wxAuiPaneInfo", "hasCloseButton", 1}, // 2557
#else
- {NULL, "wxAuiPaneInfo", "hasCloseButton", 0}, // 2554
+ {NULL, "wxAuiPaneInfo", "hasCloseButton", 0}, // 2557
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasFlag, "wxAuiPaneInfo", "hasFlag", 2}, // 2555
+ {wxAuiPaneInfo_HasFlag, "wxAuiPaneInfo", "hasFlag", 2}, // 2558
#else
- {NULL, "wxAuiPaneInfo", "hasFlag", 0}, // 2555
+ {NULL, "wxAuiPaneInfo", "hasFlag", 0}, // 2558
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasGripper, "wxAuiPaneInfo", "hasGripper", 1}, // 2556
+ {wxAuiPaneInfo_HasGripper, "wxAuiPaneInfo", "hasGripper", 1}, // 2559
#else
- {NULL, "wxAuiPaneInfo", "hasGripper", 0}, // 2556
+ {NULL, "wxAuiPaneInfo", "hasGripper", 0}, // 2559
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasGripperTop, "wxAuiPaneInfo", "hasGripperTop", 1}, // 2557
+ {wxAuiPaneInfo_HasGripperTop, "wxAuiPaneInfo", "hasGripperTop", 1}, // 2560
#else
- {NULL, "wxAuiPaneInfo", "hasGripperTop", 0}, // 2557
+ {NULL, "wxAuiPaneInfo", "hasGripperTop", 0}, // 2560
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasMaximizeButton, "wxAuiPaneInfo", "hasMaximizeButton", 1}, // 2558
+ {wxAuiPaneInfo_HasMaximizeButton, "wxAuiPaneInfo", "hasMaximizeButton", 1}, // 2561
#else
- {NULL, "wxAuiPaneInfo", "hasMaximizeButton", 0}, // 2558
+ {NULL, "wxAuiPaneInfo", "hasMaximizeButton", 0}, // 2561
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasMinimizeButton, "wxAuiPaneInfo", "hasMinimizeButton", 1}, // 2559
+ {wxAuiPaneInfo_HasMinimizeButton, "wxAuiPaneInfo", "hasMinimizeButton", 1}, // 2562
#else
- {NULL, "wxAuiPaneInfo", "hasMinimizeButton", 0}, // 2559
+ {NULL, "wxAuiPaneInfo", "hasMinimizeButton", 0}, // 2562
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasPinButton, "wxAuiPaneInfo", "hasPinButton", 1}, // 2560
+ {wxAuiPaneInfo_HasPinButton, "wxAuiPaneInfo", "hasPinButton", 1}, // 2563
#else
- {NULL, "wxAuiPaneInfo", "hasPinButton", 0}, // 2560
+ {NULL, "wxAuiPaneInfo", "hasPinButton", 0}, // 2563
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Hide, "wxAuiPaneInfo", "hide", 1}, // 2561
+ {wxAuiPaneInfo_Hide, "wxAuiPaneInfo", "hide", 1}, // 2564
#else
- {NULL, "wxAuiPaneInfo", "hide", 0}, // 2561
+ {NULL, "wxAuiPaneInfo", "hide", 0}, // 2564
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsBottomDockable, "wxAuiPaneInfo", "isBottomDockable", 1}, // 2562
+ {wxAuiPaneInfo_IsBottomDockable, "wxAuiPaneInfo", "isBottomDockable", 1}, // 2565
#else
- {NULL, "wxAuiPaneInfo", "isBottomDockable", 0}, // 2562
+ {NULL, "wxAuiPaneInfo", "isBottomDockable", 0}, // 2565
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsDocked, "wxAuiPaneInfo", "isDocked", 1}, // 2563
+ {wxAuiPaneInfo_IsDocked, "wxAuiPaneInfo", "isDocked", 1}, // 2566
#else
- {NULL, "wxAuiPaneInfo", "isDocked", 0}, // 2563
+ {NULL, "wxAuiPaneInfo", "isDocked", 0}, // 2566
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsFixed, "wxAuiPaneInfo", "isFixed", 1}, // 2564
+ {wxAuiPaneInfo_IsFixed, "wxAuiPaneInfo", "isFixed", 1}, // 2567
#else
- {NULL, "wxAuiPaneInfo", "isFixed", 0}, // 2564
+ {NULL, "wxAuiPaneInfo", "isFixed", 0}, // 2567
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsFloatable, "wxAuiPaneInfo", "isFloatable", 1}, // 2565
+ {wxAuiPaneInfo_IsFloatable, "wxAuiPaneInfo", "isFloatable", 1}, // 2568
#else
- {NULL, "wxAuiPaneInfo", "isFloatable", 0}, // 2565
+ {NULL, "wxAuiPaneInfo", "isFloatable", 0}, // 2568
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsFloating, "wxAuiPaneInfo", "isFloating", 1}, // 2566
+ {wxAuiPaneInfo_IsFloating, "wxAuiPaneInfo", "isFloating", 1}, // 2569
#else
- {NULL, "wxAuiPaneInfo", "isFloating", 0}, // 2566
+ {NULL, "wxAuiPaneInfo", "isFloating", 0}, // 2569
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsLeftDockable, "wxAuiPaneInfo", "isLeftDockable", 1}, // 2567
+ {wxAuiPaneInfo_IsLeftDockable, "wxAuiPaneInfo", "isLeftDockable", 1}, // 2570
#else
- {NULL, "wxAuiPaneInfo", "isLeftDockable", 0}, // 2567
+ {NULL, "wxAuiPaneInfo", "isLeftDockable", 0}, // 2570
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsMovable, "wxAuiPaneInfo", "isMovable", 1}, // 2568
+ {wxAuiPaneInfo_IsMovable, "wxAuiPaneInfo", "isMovable", 1}, // 2571
#else
- {NULL, "wxAuiPaneInfo", "isMovable", 0}, // 2568
+ {NULL, "wxAuiPaneInfo", "isMovable", 0}, // 2571
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsOk, "wxAuiPaneInfo", "isOk", 1}, // 2569
+ {wxAuiPaneInfo_IsOk, "wxAuiPaneInfo", "isOk", 1}, // 2572
#else
- {NULL, "wxAuiPaneInfo", "isOk", 0}, // 2569
+ {NULL, "wxAuiPaneInfo", "isOk", 0}, // 2572
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsResizable, "wxAuiPaneInfo", "isResizable", 1}, // 2570
+ {wxAuiPaneInfo_IsResizable, "wxAuiPaneInfo", "isResizable", 1}, // 2573
#else
- {NULL, "wxAuiPaneInfo", "isResizable", 0}, // 2570
+ {NULL, "wxAuiPaneInfo", "isResizable", 0}, // 2573
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsRightDockable, "wxAuiPaneInfo", "isRightDockable", 1}, // 2571
+ {wxAuiPaneInfo_IsRightDockable, "wxAuiPaneInfo", "isRightDockable", 1}, // 2574
#else
- {NULL, "wxAuiPaneInfo", "isRightDockable", 0}, // 2571
+ {NULL, "wxAuiPaneInfo", "isRightDockable", 0}, // 2574
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsShown, "wxAuiPaneInfo", "isShown", 1}, // 2572
+ {wxAuiPaneInfo_IsShown, "wxAuiPaneInfo", "isShown", 1}, // 2575
#else
- {NULL, "wxAuiPaneInfo", "isShown", 0}, // 2572
+ {NULL, "wxAuiPaneInfo", "isShown", 0}, // 2575
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsToolbar, "wxAuiPaneInfo", "isToolbar", 1}, // 2573
+ {wxAuiPaneInfo_IsToolbar, "wxAuiPaneInfo", "isToolbar", 1}, // 2576
#else
- {NULL, "wxAuiPaneInfo", "isToolbar", 0}, // 2573
+ {NULL, "wxAuiPaneInfo", "isToolbar", 0}, // 2576
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsTopDockable, "wxAuiPaneInfo", "isTopDockable", 1}, // 2574
+ {wxAuiPaneInfo_IsTopDockable, "wxAuiPaneInfo", "isTopDockable", 1}, // 2577
#else
- {NULL, "wxAuiPaneInfo", "isTopDockable", 0}, // 2574
+ {NULL, "wxAuiPaneInfo", "isTopDockable", 0}, // 2577
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Layer, "wxAuiPaneInfo", "layer", 2}, // 2575
+ {wxAuiPaneInfo_Layer, "wxAuiPaneInfo", "layer", 2}, // 2578
#else
- {NULL, "wxAuiPaneInfo", "layer", 0}, // 2575
+ {NULL, "wxAuiPaneInfo", "layer", 0}, // 2578
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Left, "wxAuiPaneInfo", "left", 1}, // 2576
+ {wxAuiPaneInfo_Left, "wxAuiPaneInfo", "left", 1}, // 2579
#else
- {NULL, "wxAuiPaneInfo", "left", 0}, // 2576
+ {NULL, "wxAuiPaneInfo", "left", 0}, // 2579
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_LeftDockable, "wxAuiPaneInfo", "leftDockable", 2}, // 2577
+ {wxAuiPaneInfo_LeftDockable, "wxAuiPaneInfo", "leftDockable", 2}, // 2580
#else
- {NULL, "wxAuiPaneInfo", "leftDockable", 0}, // 2577
+ {NULL, "wxAuiPaneInfo", "leftDockable", 0}, // 2580
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MaxSize_1, "wxAuiPaneInfo", "maxSize", 2}, // 2578
+ {wxAuiPaneInfo_MaxSize_1, "wxAuiPaneInfo", "maxSize", 2}, // 2581
#else
- {NULL, "wxAuiPaneInfo", "maxSize", 0}, // 2578
+ {NULL, "wxAuiPaneInfo", "maxSize", 0}, // 2581
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MaxSize_2, "wxAuiPaneInfo", "maxSize", 3}, // 2579
+ {wxAuiPaneInfo_MaxSize_2, "wxAuiPaneInfo", "maxSize", 3}, // 2582
#else
- {NULL, "wxAuiPaneInfo", "maxSize", 0}, // 2579
+ {NULL, "wxAuiPaneInfo", "maxSize", 0}, // 2582
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MaximizeButton, "wxAuiPaneInfo", "maximizeButton", 2}, // 2580
+ {wxAuiPaneInfo_MaximizeButton, "wxAuiPaneInfo", "maximizeButton", 2}, // 2583
#else
- {NULL, "wxAuiPaneInfo", "maximizeButton", 0}, // 2580
+ {NULL, "wxAuiPaneInfo", "maximizeButton", 0}, // 2583
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MinSize_1, "wxAuiPaneInfo", "minSize", 2}, // 2581
+ {wxAuiPaneInfo_MinSize_1, "wxAuiPaneInfo", "minSize", 2}, // 2584
#else
- {NULL, "wxAuiPaneInfo", "minSize", 0}, // 2581
+ {NULL, "wxAuiPaneInfo", "minSize", 0}, // 2584
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MinSize_2, "wxAuiPaneInfo", "minSize", 3}, // 2582
+ {wxAuiPaneInfo_MinSize_2, "wxAuiPaneInfo", "minSize", 3}, // 2585
#else
- {NULL, "wxAuiPaneInfo", "minSize", 0}, // 2582
+ {NULL, "wxAuiPaneInfo", "minSize", 0}, // 2585
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MinimizeButton, "wxAuiPaneInfo", "minimizeButton", 2}, // 2583
+ {wxAuiPaneInfo_MinimizeButton, "wxAuiPaneInfo", "minimizeButton", 2}, // 2586
#else
- {NULL, "wxAuiPaneInfo", "minimizeButton", 0}, // 2583
+ {NULL, "wxAuiPaneInfo", "minimizeButton", 0}, // 2586
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Movable, "wxAuiPaneInfo", "movable", 2}, // 2584
+ {wxAuiPaneInfo_Movable, "wxAuiPaneInfo", "movable", 2}, // 2587
#else
- {NULL, "wxAuiPaneInfo", "movable", 0}, // 2584
+ {NULL, "wxAuiPaneInfo", "movable", 0}, // 2587
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Name, "wxAuiPaneInfo", "name", 2}, // 2585
+ {wxAuiPaneInfo_Name, "wxAuiPaneInfo", "name", 2}, // 2588
#else
- {NULL, "wxAuiPaneInfo", "name", 0}, // 2585
+ {NULL, "wxAuiPaneInfo", "name", 0}, // 2588
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_PaneBorder, "wxAuiPaneInfo", "paneBorder", 2}, // 2586
+ {wxAuiPaneInfo_PaneBorder, "wxAuiPaneInfo", "paneBorder", 2}, // 2589
#else
- {NULL, "wxAuiPaneInfo", "paneBorder", 0}, // 2586
+ {NULL, "wxAuiPaneInfo", "paneBorder", 0}, // 2589
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_PinButton, "wxAuiPaneInfo", "pinButton", 2}, // 2587
+ {wxAuiPaneInfo_PinButton, "wxAuiPaneInfo", "pinButton", 2}, // 2590
#else
- {NULL, "wxAuiPaneInfo", "pinButton", 0}, // 2587
+ {NULL, "wxAuiPaneInfo", "pinButton", 0}, // 2590
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Position, "wxAuiPaneInfo", "position", 2}, // 2588
+ {wxAuiPaneInfo_Position, "wxAuiPaneInfo", "position", 2}, // 2591
#else
- {NULL, "wxAuiPaneInfo", "position", 0}, // 2588
+ {NULL, "wxAuiPaneInfo", "position", 0}, // 2591
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Resizable, "wxAuiPaneInfo", "resizable", 2}, // 2589
+ {wxAuiPaneInfo_Resizable, "wxAuiPaneInfo", "resizable", 2}, // 2592
#else
- {NULL, "wxAuiPaneInfo", "resizable", 0}, // 2589
+ {NULL, "wxAuiPaneInfo", "resizable", 0}, // 2592
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Right, "wxAuiPaneInfo", "right", 1}, // 2590
+ {wxAuiPaneInfo_Right, "wxAuiPaneInfo", "right", 1}, // 2593
#else
- {NULL, "wxAuiPaneInfo", "right", 0}, // 2590
+ {NULL, "wxAuiPaneInfo", "right", 0}, // 2593
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_RightDockable, "wxAuiPaneInfo", "rightDockable", 2}, // 2591
+ {wxAuiPaneInfo_RightDockable, "wxAuiPaneInfo", "rightDockable", 2}, // 2594
#else
- {NULL, "wxAuiPaneInfo", "rightDockable", 0}, // 2591
+ {NULL, "wxAuiPaneInfo", "rightDockable", 0}, // 2594
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Row, "wxAuiPaneInfo", "row", 2}, // 2592
+ {wxAuiPaneInfo_Row, "wxAuiPaneInfo", "row", 2}, // 2595
#else
- {NULL, "wxAuiPaneInfo", "row", 0}, // 2592
+ {NULL, "wxAuiPaneInfo", "row", 0}, // 2595
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_SafeSet, "wxAuiPaneInfo", "safeSet", 2}, // 2593
+ {wxAuiPaneInfo_SafeSet, "wxAuiPaneInfo", "safeSet", 2}, // 2596
#else
- {NULL, "wxAuiPaneInfo", "safeSet", 0}, // 2593
+ {NULL, "wxAuiPaneInfo", "safeSet", 0}, // 2596
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_SetFlag, "wxAuiPaneInfo", "setFlag", 3}, // 2594
+ {wxAuiPaneInfo_SetFlag, "wxAuiPaneInfo", "setFlag", 3}, // 2597
#else
- {NULL, "wxAuiPaneInfo", "setFlag", 0}, // 2594
+ {NULL, "wxAuiPaneInfo", "setFlag", 0}, // 2597
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Show, "wxAuiPaneInfo", "show", 2}, // 2595
+ {wxAuiPaneInfo_Show, "wxAuiPaneInfo", "show", 2}, // 2598
#else
- {NULL, "wxAuiPaneInfo", "show", 0}, // 2595
+ {NULL, "wxAuiPaneInfo", "show", 0}, // 2598
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_ToolbarPane, "wxAuiPaneInfo", "toolbarPane", 1}, // 2596
+ {wxAuiPaneInfo_ToolbarPane, "wxAuiPaneInfo", "toolbarPane", 1}, // 2599
#else
- {NULL, "wxAuiPaneInfo", "toolbarPane", 0}, // 2596
+ {NULL, "wxAuiPaneInfo", "toolbarPane", 0}, // 2599
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Top, "wxAuiPaneInfo", "top", 1}, // 2597
+ {wxAuiPaneInfo_Top, "wxAuiPaneInfo", "top", 1}, // 2600
#else
- {NULL, "wxAuiPaneInfo", "top", 0}, // 2597
+ {NULL, "wxAuiPaneInfo", "top", 0}, // 2600
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_TopDockable, "wxAuiPaneInfo", "topDockable", 2}, // 2598
+ {wxAuiPaneInfo_TopDockable, "wxAuiPaneInfo", "topDockable", 2}, // 2601
#else
- {NULL, "wxAuiPaneInfo", "topDockable", 0}, // 2598
+ {NULL, "wxAuiPaneInfo", "topDockable", 0}, // 2601
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Window, "wxAuiPaneInfo", "window", 2}, // 2599
+ {wxAuiPaneInfo_Window, "wxAuiPaneInfo", "window", 2}, // 2602
#else
- {NULL, "wxAuiPaneInfo", "window", 0}, // 2599
+ {NULL, "wxAuiPaneInfo", "window", 0}, // 2602
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetWindow, "wxAuiPaneInfo", "getWindow", 1}, // 2600
+ {wxAuiPaneInfo_GetWindow, "wxAuiPaneInfo", "getWindow", 1}, // 2603
#else
- {NULL, "wxAuiPaneInfo", "getWindow", 0}, // 2600
+ {NULL, "wxAuiPaneInfo", "getWindow", 0}, // 2603
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetFrame, "wxAuiPaneInfo", "getFrame", 1}, // 2601
+ {wxAuiPaneInfo_GetFrame, "wxAuiPaneInfo", "getFrame", 1}, // 2604
#else
- {NULL, "wxAuiPaneInfo", "getFrame", 0}, // 2601
+ {NULL, "wxAuiPaneInfo", "getFrame", 0}, // 2604
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetDirection, "wxAuiPaneInfo", "getDirection", 1}, // 2602
+ {wxAuiPaneInfo_GetDirection, "wxAuiPaneInfo", "getDirection", 1}, // 2605
#else
- {NULL, "wxAuiPaneInfo", "getDirection", 0}, // 2602
+ {NULL, "wxAuiPaneInfo", "getDirection", 0}, // 2605
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetLayer, "wxAuiPaneInfo", "getLayer", 1}, // 2603
+ {wxAuiPaneInfo_GetLayer, "wxAuiPaneInfo", "getLayer", 1}, // 2606
#else
- {NULL, "wxAuiPaneInfo", "getLayer", 0}, // 2603
+ {NULL, "wxAuiPaneInfo", "getLayer", 0}, // 2606
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetRow, "wxAuiPaneInfo", "getRow", 1}, // 2604
+ {wxAuiPaneInfo_GetRow, "wxAuiPaneInfo", "getRow", 1}, // 2607
#else
- {NULL, "wxAuiPaneInfo", "getRow", 0}, // 2604
+ {NULL, "wxAuiPaneInfo", "getRow", 0}, // 2607
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetPosition, "wxAuiPaneInfo", "getPosition", 1}, // 2605
+ {wxAuiPaneInfo_GetPosition, "wxAuiPaneInfo", "getPosition", 1}, // 2608
#else
- {NULL, "wxAuiPaneInfo", "getPosition", 0}, // 2605
+ {NULL, "wxAuiPaneInfo", "getPosition", 0}, // 2608
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetFloatingPosition, "wxAuiPaneInfo", "getFloatingPosition", 1}, // 2606
+ {wxAuiPaneInfo_GetFloatingPosition, "wxAuiPaneInfo", "getFloatingPosition", 1}, // 2609
#else
- {NULL, "wxAuiPaneInfo", "getFloatingPosition", 0}, // 2606
+ {NULL, "wxAuiPaneInfo", "getFloatingPosition", 0}, // 2609
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetFloatingSize, "wxAuiPaneInfo", "getFloatingSize", 1}, // 2607
+ {wxAuiPaneInfo_GetFloatingSize, "wxAuiPaneInfo", "getFloatingSize", 1}, // 2610
#else
- {NULL, "wxAuiPaneInfo", "getFloatingSize", 0}, // 2607
+ {NULL, "wxAuiPaneInfo", "getFloatingSize", 0}, // 2610
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_destroy, "wxAuiPaneInfo", "'Destroy'", 1}, // 2608
+ {wxAuiPaneInfo_destroy, "wxAuiPaneInfo", "'Destroy'", 1}, // 2611
#else
- {NULL, "wxAuiPaneInfo", "'Destroy'", 0}, // 2608
+ {NULL, "wxAuiPaneInfo", "'Destroy'", 0}, // 2611
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_new_0, "wxAuiNotebook", "new", 0}, // 2609
+ {wxAuiNotebook_new_0, "wxAuiNotebook", "new", 0}, // 2612
#else
- {NULL, "wxAuiNotebook", "new", 0}, // 2609
+ {NULL, "wxAuiNotebook", "new", 0}, // 2612
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_new_2, "wxAuiNotebook", "new", 2}, // 2610
+ {wxAuiNotebook_new_2, "wxAuiNotebook", "new", 2}, // 2613
#else
- {NULL, "wxAuiNotebook", "new", 0}, // 2610
+ {NULL, "wxAuiNotebook", "new", 0}, // 2613
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_AddPage_3, "wxAuiNotebook", "addPage", 4}, // 2611
+ {wxAuiNotebook_AddPage_3, "wxAuiNotebook", "addPage", 4}, // 2614
#else
- {NULL, "wxAuiNotebook", "addPage", 0}, // 2611
+ {NULL, "wxAuiNotebook", "addPage", 0}, // 2614
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_AddPage_4, "wxAuiNotebook", "addPage", 5}, // 2612
+ {wxAuiNotebook_AddPage_4, "wxAuiNotebook", "addPage", 5}, // 2615
#else
- {NULL, "wxAuiNotebook", "addPage", 0}, // 2612
+ {NULL, "wxAuiNotebook", "addPage", 0}, // 2615
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_Create_2, "wxAuiNotebook", "create", 3}, // 2613
+ {wxAuiNotebook_Create_2, "wxAuiNotebook", "create", 3}, // 2616
#else
- {NULL, "wxAuiNotebook", "create", 0}, // 2613
+ {NULL, "wxAuiNotebook", "create", 0}, // 2616
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_Create_3, "wxAuiNotebook", "create", 4}, // 2614
+ {wxAuiNotebook_Create_3, "wxAuiNotebook", "create", 4}, // 2617
#else
- {NULL, "wxAuiNotebook", "create", 0}, // 2614
+ {NULL, "wxAuiNotebook", "create", 0}, // 2617
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_DeletePage, "wxAuiNotebook", "deletePage", 2}, // 2615
+ {wxAuiNotebook_DeletePage, "wxAuiNotebook", "deletePage", 2}, // 2618
#else
- {NULL, "wxAuiNotebook", "deletePage", 0}, // 2615
+ {NULL, "wxAuiNotebook", "deletePage", 0}, // 2618
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetArtProvider, "wxAuiNotebook", "getArtProvider", 1}, // 2616
+ {wxAuiNotebook_GetArtProvider, "wxAuiNotebook", "getArtProvider", 1}, // 2619
#else
- {NULL, "wxAuiNotebook", "getArtProvider", 0}, // 2616
+ {NULL, "wxAuiNotebook", "getArtProvider", 0}, // 2619
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPage, "wxAuiNotebook", "getPage", 2}, // 2617
+ {wxAuiNotebook_GetPage, "wxAuiNotebook", "getPage", 2}, // 2620
#else
- {NULL, "wxAuiNotebook", "getPage", 0}, // 2617
+ {NULL, "wxAuiNotebook", "getPage", 0}, // 2620
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPageBitmap, "wxAuiNotebook", "getPageBitmap", 2}, // 2618
+ {wxAuiNotebook_GetPageBitmap, "wxAuiNotebook", "getPageBitmap", 2}, // 2621
#else
- {NULL, "wxAuiNotebook", "getPageBitmap", 0}, // 2618
+ {NULL, "wxAuiNotebook", "getPageBitmap", 0}, // 2621
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPageCount, "wxAuiNotebook", "getPageCount", 1}, // 2619
+ {wxAuiNotebook_GetPageCount, "wxAuiNotebook", "getPageCount", 1}, // 2622
#else
- {NULL, "wxAuiNotebook", "getPageCount", 0}, // 2619
+ {NULL, "wxAuiNotebook", "getPageCount", 0}, // 2622
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPageIndex, "wxAuiNotebook", "getPageIndex", 2}, // 2620
+ {wxAuiNotebook_GetPageIndex, "wxAuiNotebook", "getPageIndex", 2}, // 2623
#else
- {NULL, "wxAuiNotebook", "getPageIndex", 0}, // 2620
+ {NULL, "wxAuiNotebook", "getPageIndex", 0}, // 2623
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPageText, "wxAuiNotebook", "getPageText", 2}, // 2621
+ {wxAuiNotebook_GetPageText, "wxAuiNotebook", "getPageText", 2}, // 2624
#else
- {NULL, "wxAuiNotebook", "getPageText", 0}, // 2621
+ {NULL, "wxAuiNotebook", "getPageText", 0}, // 2624
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetSelection, "wxAuiNotebook", "getSelection", 1}, // 2622
+ {wxAuiNotebook_GetSelection, "wxAuiNotebook", "getSelection", 1}, // 2625
#else
- {NULL, "wxAuiNotebook", "getSelection", 0}, // 2622
+ {NULL, "wxAuiNotebook", "getSelection", 0}, // 2625
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_InsertPage_4, "wxAuiNotebook", "insertPage", 5}, // 2623
+ {wxAuiNotebook_InsertPage_4, "wxAuiNotebook", "insertPage", 5}, // 2626
#else
- {NULL, "wxAuiNotebook", "insertPage", 0}, // 2623
+ {NULL, "wxAuiNotebook", "insertPage", 0}, // 2626
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_InsertPage_5, "wxAuiNotebook", "insertPage", 6}, // 2624
+ {wxAuiNotebook_InsertPage_5, "wxAuiNotebook", "insertPage", 6}, // 2627
#else
- {NULL, "wxAuiNotebook", "insertPage", 0}, // 2624
+ {NULL, "wxAuiNotebook", "insertPage", 0}, // 2627
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_RemovePage, "wxAuiNotebook", "removePage", 2}, // 2625
+ {wxAuiNotebook_RemovePage, "wxAuiNotebook", "removePage", 2}, // 2628
#else
- {NULL, "wxAuiNotebook", "removePage", 0}, // 2625
+ {NULL, "wxAuiNotebook", "removePage", 0}, // 2628
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetArtProvider, "wxAuiNotebook", "setArtProvider", 2}, // 2626
+ {wxAuiNotebook_SetArtProvider, "wxAuiNotebook", "setArtProvider", 2}, // 2629
#else
- {NULL, "wxAuiNotebook", "setArtProvider", 0}, // 2626
+ {NULL, "wxAuiNotebook", "setArtProvider", 0}, // 2629
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetFont, "wxAuiNotebook", "setFont", 2}, // 2627
+ {wxAuiNotebook_SetFont, "wxAuiNotebook", "setFont", 2}, // 2630
#else
- {NULL, "wxAuiNotebook", "setFont", 0}, // 2627
+ {NULL, "wxAuiNotebook", "setFont", 0}, // 2630
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetPageBitmap, "wxAuiNotebook", "setPageBitmap", 3}, // 2628
+ {wxAuiNotebook_SetPageBitmap, "wxAuiNotebook", "setPageBitmap", 3}, // 2631
#else
- {NULL, "wxAuiNotebook", "setPageBitmap", 0}, // 2628
+ {NULL, "wxAuiNotebook", "setPageBitmap", 0}, // 2631
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetPageText, "wxAuiNotebook", "setPageText", 3}, // 2629
+ {wxAuiNotebook_SetPageText, "wxAuiNotebook", "setPageText", 3}, // 2632
#else
- {NULL, "wxAuiNotebook", "setPageText", 0}, // 2629
+ {NULL, "wxAuiNotebook", "setPageText", 0}, // 2632
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetSelection, "wxAuiNotebook", "setSelection", 2}, // 2630
+ {wxAuiNotebook_SetSelection, "wxAuiNotebook", "setSelection", 2}, // 2633
#else
- {NULL, "wxAuiNotebook", "setSelection", 0}, // 2630
+ {NULL, "wxAuiNotebook", "setSelection", 0}, // 2633
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetTabCtrlHeight, "wxAuiNotebook", "setTabCtrlHeight", 2}, // 2631
+ {wxAuiNotebook_SetTabCtrlHeight, "wxAuiNotebook", "setTabCtrlHeight", 2}, // 2634
#else
- {NULL, "wxAuiNotebook", "setTabCtrlHeight", 0}, // 2631
+ {NULL, "wxAuiNotebook", "setTabCtrlHeight", 0}, // 2634
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetUniformBitmapSize, "wxAuiNotebook", "setUniformBitmapSize", 2}, // 2632
+ {wxAuiNotebook_SetUniformBitmapSize, "wxAuiNotebook", "setUniformBitmapSize", 2}, // 2635
#else
- {NULL, "wxAuiNotebook", "setUniformBitmapSize", 0}, // 2632
+ {NULL, "wxAuiNotebook", "setUniformBitmapSize", 0}, // 2635
#endif // wxUSE_AUI
#if wxUSE_AUI
- {NULL, "wxAuiNotebook", "'Destroy'", 1}, // 2633 obj destructor wxAuiNotebook_destroy
+ {NULL, "wxAuiNotebook", "'Destroy'", 1}, // 2636 obj destructor wxAuiNotebook_destroy
#else
- {NULL, "wxAuiNotebook", "'Destroy'", 0}, // 2633
+ {NULL, "wxAuiNotebook", "'Destroy'", 0}, // 2636
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetFlags, "wxAuiTabArt", "setFlags", 2}, // 2634
+ {wxAuiTabArt_SetFlags, "wxAuiTabArt", "setFlags", 2}, // 2637
#else
- {NULL, "wxAuiTabArt", "setFlags", 0}, // 2634
+ {NULL, "wxAuiTabArt", "setFlags", 0}, // 2637
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetMeasuringFont, "wxAuiTabArt", "setMeasuringFont", 2}, // 2635
+ {wxAuiTabArt_SetMeasuringFont, "wxAuiTabArt", "setMeasuringFont", 2}, // 2638
#else
- {NULL, "wxAuiTabArt", "setMeasuringFont", 0}, // 2635
+ {NULL, "wxAuiTabArt", "setMeasuringFont", 0}, // 2638
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetNormalFont, "wxAuiTabArt", "setNormalFont", 2}, // 2636
+ {wxAuiTabArt_SetNormalFont, "wxAuiTabArt", "setNormalFont", 2}, // 2639
#else
- {NULL, "wxAuiTabArt", "setNormalFont", 0}, // 2636
+ {NULL, "wxAuiTabArt", "setNormalFont", 0}, // 2639
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetSelectedFont, "wxAuiTabArt", "setSelectedFont", 2}, // 2637
+ {wxAuiTabArt_SetSelectedFont, "wxAuiTabArt", "setSelectedFont", 2}, // 2640
#else
- {NULL, "wxAuiTabArt", "setSelectedFont", 0}, // 2637
+ {NULL, "wxAuiTabArt", "setSelectedFont", 0}, // 2640
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetColour, "wxAuiTabArt", "setColour", 2}, // 2638
+ {wxAuiTabArt_SetColour, "wxAuiTabArt", "setColour", 2}, // 2641
#else
- {NULL, "wxAuiTabArt", "setColour", 0}, // 2638
+ {NULL, "wxAuiTabArt", "setColour", 0}, // 2641
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetActiveColour, "wxAuiTabArt", "setActiveColour", 2}, // 2639
+ {wxAuiTabArt_SetActiveColour, "wxAuiTabArt", "setActiveColour", 2}, // 2642
#else
- {NULL, "wxAuiTabArt", "setActiveColour", 0}, // 2639
+ {NULL, "wxAuiTabArt", "setActiveColour", 0}, // 2642
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_GetColour, "wxAuiDockArt", "getColour", 2}, // 2640
+ {wxAuiDockArt_GetColour, "wxAuiDockArt", "getColour", 2}, // 2643
#else
- {NULL, "wxAuiDockArt", "getColour", 0}, // 2640
+ {NULL, "wxAuiDockArt", "getColour", 0}, // 2643
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_GetFont, "wxAuiDockArt", "getFont", 2}, // 2641
+ {wxAuiDockArt_GetFont, "wxAuiDockArt", "getFont", 2}, // 2644
#else
- {NULL, "wxAuiDockArt", "getFont", 0}, // 2641
+ {NULL, "wxAuiDockArt", "getFont", 0}, // 2644
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_GetMetric, "wxAuiDockArt", "getMetric", 2}, // 2642
+ {wxAuiDockArt_GetMetric, "wxAuiDockArt", "getMetric", 2}, // 2645
#else
- {NULL, "wxAuiDockArt", "getMetric", 0}, // 2642
+ {NULL, "wxAuiDockArt", "getMetric", 0}, // 2645
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_SetColour, "wxAuiDockArt", "setColour", 3}, // 2643
+ {wxAuiDockArt_SetColour, "wxAuiDockArt", "setColour", 3}, // 2646
#else
- {NULL, "wxAuiDockArt", "setColour", 0}, // 2643
+ {NULL, "wxAuiDockArt", "setColour", 0}, // 2646
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_SetFont, "wxAuiDockArt", "setFont", 3}, // 2644
+ {wxAuiDockArt_SetFont, "wxAuiDockArt", "setFont", 3}, // 2647
#else
- {NULL, "wxAuiDockArt", "setFont", 0}, // 2644
+ {NULL, "wxAuiDockArt", "setFont", 0}, // 2647
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_SetMetric, "wxAuiDockArt", "setMetric", 3}, // 2645
+ {wxAuiDockArt_SetMetric, "wxAuiDockArt", "setMetric", 3}, // 2648
#else
- {NULL, "wxAuiDockArt", "setMetric", 0}, // 2645
+ {NULL, "wxAuiDockArt", "setMetric", 0}, // 2648
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiSimpleTabArt_new, "wxAuiSimpleTabArt", "new", 0}, // 2646
+ {wxAuiSimpleTabArt_new, "wxAuiSimpleTabArt", "new", 0}, // 2649
#else
- {NULL, "wxAuiSimpleTabArt", "new", 0}, // 2646
+ {NULL, "wxAuiSimpleTabArt", "new", 0}, // 2649
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiSimpleTabArt_destroy, "wxAuiSimpleTabArt", "'Destroy'", 1}, // 2647
+ {wxAuiSimpleTabArt_destroy, "wxAuiSimpleTabArt", "'Destroy'", 1}, // 2650
#else
- {NULL, "wxAuiSimpleTabArt", "'Destroy'", 0}, // 2647
+ {NULL, "wxAuiSimpleTabArt", "'Destroy'", 0}, // 2650
#endif // wxUSE_AUI
- {wxMDIParentFrame_new_0, "wxMDIParentFrame", "new", 0}, // 2648
- {wxMDIParentFrame_new_4, "wxMDIParentFrame", "new", 4}, // 2649
- {NULL, "wxMDIParentFrame", "destroy", 1}, // 2650 obj destructor wxMDIParentFrame_destruct
- {wxMDIParentFrame_ActivateNext, "wxMDIParentFrame", "activateNext", 1}, // 2651
- {wxMDIParentFrame_ActivatePrevious, "wxMDIParentFrame", "activatePrevious", 1}, // 2652
- {wxMDIParentFrame_ArrangeIcons, "wxMDIParentFrame", "arrangeIcons", 1}, // 2653
- {wxMDIParentFrame_Cascade, "wxMDIParentFrame", "cascade", 1}, // 2654
- {wxMDIParentFrame_Create, "wxMDIParentFrame", "create", 5}, // 2655
- {wxMDIParentFrame_GetActiveChild, "wxMDIParentFrame", "getActiveChild", 1}, // 2656
- {wxMDIParentFrame_GetClientWindow, "wxMDIParentFrame", "getClientWindow", 1}, // 2657
- {wxMDIParentFrame_Tile, "wxMDIParentFrame", "tile", 2}, // 2658
- {wxMDIChildFrame_new_0, "wxMDIChildFrame", "new", 0}, // 2659
- {wxMDIChildFrame_new_4, "wxMDIChildFrame", "new", 4}, // 2660
- {NULL, "wxMDIChildFrame", "destroy", 1}, // 2661 obj destructor wxMDIChildFrame_destruct
- {wxMDIChildFrame_Activate, "wxMDIChildFrame", "activate", 1}, // 2662
- {wxMDIChildFrame_Create, "wxMDIChildFrame", "create", 5}, // 2663
- {wxMDIChildFrame_Maximize, "wxMDIChildFrame", "maximize", 2}, // 2664
- {wxMDIChildFrame_Restore, "wxMDIChildFrame", "restore", 1}, // 2665
- {wxMDIClientWindow_new, "wxMDIClientWindow", "new", 0}, // 2666
- {wxMDIClientWindow_CreateClient, "wxMDIClientWindow", "createClient", 3}, // 2667
- {NULL, "wxMDIClientWindow", "'Destroy'", 1}, // 2668 obj destructor wxMDIClientWindow_destroy
- {wxLayoutAlgorithm_new, "wxLayoutAlgorithm", "new", 0}, // 2669
- {NULL, "wxLayoutAlgorithm", "destroy", 1}, // 2670 obj destructor wxLayoutAlgorithm_destruct
- {wxLayoutAlgorithm_LayoutFrame, "wxLayoutAlgorithm", "layoutFrame", 3}, // 2671
- {wxLayoutAlgorithm_LayoutMDIFrame, "wxLayoutAlgorithm", "layoutMDIFrame", 3}, // 2672
- {wxLayoutAlgorithm_LayoutWindow, "wxLayoutAlgorithm", "layoutWindow", 3}, // 2673
- {wxEvent_GetId, "wxEvent", "getId", 1}, // 2674
- {wxEvent_GetSkipped, "wxEvent", "getSkipped", 1}, // 2675
- {wxEvent_GetTimestamp, "wxEvent", "getTimestamp", 1}, // 2676
- {wxEvent_IsCommandEvent, "wxEvent", "isCommandEvent", 1}, // 2677
- {wxEvent_ResumePropagation, "wxEvent", "resumePropagation", 2}, // 2678
- {wxEvent_ShouldPropagate, "wxEvent", "shouldPropagate", 1}, // 2679
- {wxEvent_Skip, "wxEvent", "skip", 2}, // 2680
- {wxEvent_StopPropagation, "wxEvent", "stopPropagation", 1}, // 2681
- {wxCommandEvent_getClientData, "wxCommandEvent", "getClientData", 1}, // 2682
- {wxCommandEvent_GetExtraLong, "wxCommandEvent", "getExtraLong", 1}, // 2683
- {wxCommandEvent_GetInt, "wxCommandEvent", "getInt", 1}, // 2684
- {wxCommandEvent_GetSelection, "wxCommandEvent", "getSelection", 1}, // 2685
- {wxCommandEvent_GetString, "wxCommandEvent", "getString", 1}, // 2686
- {wxCommandEvent_IsChecked, "wxCommandEvent", "isChecked", 1}, // 2687
- {wxCommandEvent_IsSelection, "wxCommandEvent", "isSelection", 1}, // 2688
- {wxCommandEvent_SetInt, "wxCommandEvent", "setInt", 2}, // 2689
- {wxCommandEvent_SetString, "wxCommandEvent", "setString", 2}, // 2690
- {wxScrollEvent_GetOrientation, "wxScrollEvent", "getOrientation", 1}, // 2691
- {wxScrollEvent_GetPosition, "wxScrollEvent", "getPosition", 1}, // 2692
- {wxScrollWinEvent_GetOrientation, "wxScrollWinEvent", "getOrientation", 1}, // 2693
- {wxScrollWinEvent_GetPosition, "wxScrollWinEvent", "getPosition", 1}, // 2694
- {wxMouseEvent_AltDown, "wxMouseEvent", "altDown", 1}, // 2695
- {wxMouseEvent_Button, "wxMouseEvent", "button", 2}, // 2696
- {wxMouseEvent_ButtonDClick, "wxMouseEvent", "buttonDClick", 2}, // 2697
- {wxMouseEvent_ButtonDown, "wxMouseEvent", "buttonDown", 2}, // 2698
- {wxMouseEvent_ButtonUp, "wxMouseEvent", "buttonUp", 2}, // 2699
- {wxMouseEvent_CmdDown, "wxMouseEvent", "cmdDown", 1}, // 2700
- {wxMouseEvent_ControlDown, "wxMouseEvent", "controlDown", 1}, // 2701
- {wxMouseEvent_Dragging, "wxMouseEvent", "dragging", 1}, // 2702
- {wxMouseEvent_Entering, "wxMouseEvent", "entering", 1}, // 2703
- {wxMouseEvent_GetButton, "wxMouseEvent", "getButton", 1}, // 2704
- {wxMouseEvent_GetPosition, "wxMouseEvent", "getPosition", 1}, // 2705
- {NULL, "", "", 0}, // 2706
- {wxMouseEvent_GetLogicalPosition, "wxMouseEvent", "getLogicalPosition", 2}, // 2707
- {wxMouseEvent_GetLinesPerAction, "wxMouseEvent", "getLinesPerAction", 1}, // 2708
- {wxMouseEvent_GetWheelRotation, "wxMouseEvent", "getWheelRotation", 1}, // 2709
- {wxMouseEvent_GetWheelDelta, "wxMouseEvent", "getWheelDelta", 1}, // 2710
- {wxMouseEvent_GetX, "wxMouseEvent", "getX", 1}, // 2711
- {wxMouseEvent_GetY, "wxMouseEvent", "getY", 1}, // 2712
- {wxMouseEvent_IsButton, "wxMouseEvent", "isButton", 1}, // 2713
- {wxMouseEvent_IsPageScroll, "wxMouseEvent", "isPageScroll", 1}, // 2714
- {wxMouseEvent_Leaving, "wxMouseEvent", "leaving", 1}, // 2715
- {wxMouseEvent_LeftDClick, "wxMouseEvent", "leftDClick", 1}, // 2716
- {wxMouseEvent_LeftDown, "wxMouseEvent", "leftDown", 1}, // 2717
- {wxMouseEvent_LeftIsDown, "wxMouseEvent", "leftIsDown", 1}, // 2718
- {wxMouseEvent_LeftUp, "wxMouseEvent", "leftUp", 1}, // 2719
- {wxMouseEvent_MetaDown, "wxMouseEvent", "metaDown", 1}, // 2720
- {wxMouseEvent_MiddleDClick, "wxMouseEvent", "middleDClick", 1}, // 2721
- {wxMouseEvent_MiddleDown, "wxMouseEvent", "middleDown", 1}, // 2722
- {wxMouseEvent_MiddleIsDown, "wxMouseEvent", "middleIsDown", 1}, // 2723
- {wxMouseEvent_MiddleUp, "wxMouseEvent", "middleUp", 1}, // 2724
- {wxMouseEvent_Moving, "wxMouseEvent", "moving", 1}, // 2725
- {wxMouseEvent_RightDClick, "wxMouseEvent", "rightDClick", 1}, // 2726
- {wxMouseEvent_RightDown, "wxMouseEvent", "rightDown", 1}, // 2727
- {wxMouseEvent_RightIsDown, "wxMouseEvent", "rightIsDown", 1}, // 2728
- {wxMouseEvent_RightUp, "wxMouseEvent", "rightUp", 1}, // 2729
- {wxMouseEvent_ShiftDown, "wxMouseEvent", "shiftDown", 1}, // 2730
- {wxMouseEvent_GetWheelAxis, "wxMouseEvent", "getWheelAxis", 1}, // 2731
- {wxMouseEvent_Aux1DClick, "wxMouseEvent", "aux1DClick", 1}, // 2732
- {wxMouseEvent_Aux1Down, "wxMouseEvent", "aux1Down", 1}, // 2733
- {wxMouseEvent_Aux1Up, "wxMouseEvent", "aux1Up", 1}, // 2734
- {wxMouseEvent_Aux2DClick, "wxMouseEvent", "aux2DClick", 1}, // 2735
- {wxMouseEvent_Aux2Down, "wxMouseEvent", "aux2Down", 1}, // 2736
- {wxMouseEvent_Aux2Up, "wxMouseEvent", "aux2Up", 1}, // 2737
- {wxSetCursorEvent_GetCursor, "wxSetCursorEvent", "getCursor", 1}, // 2738
- {wxSetCursorEvent_GetX, "wxSetCursorEvent", "getX", 1}, // 2739
- {wxSetCursorEvent_GetY, "wxSetCursorEvent", "getY", 1}, // 2740
- {wxSetCursorEvent_HasCursor, "wxSetCursorEvent", "hasCursor", 1}, // 2741
- {wxSetCursorEvent_SetCursor, "wxSetCursorEvent", "setCursor", 2}, // 2742
- {wxKeyEvent_AltDown, "wxKeyEvent", "altDown", 1}, // 2743
- {wxKeyEvent_CmdDown, "wxKeyEvent", "cmdDown", 1}, // 2744
- {wxKeyEvent_ControlDown, "wxKeyEvent", "controlDown", 1}, // 2745
- {wxKeyEvent_GetKeyCode, "wxKeyEvent", "getKeyCode", 1}, // 2746
- {wxKeyEvent_GetModifiers, "wxKeyEvent", "getModifiers", 1}, // 2747
- {wxKeyEvent_GetPosition, "wxKeyEvent", "getPosition", 1}, // 2748
- {NULL, "", "", 0}, // 2749
- {wxKeyEvent_GetRawKeyCode, "wxKeyEvent", "getRawKeyCode", 1}, // 2750
- {wxKeyEvent_GetRawKeyFlags, "wxKeyEvent", "getRawKeyFlags", 1}, // 2751
- {wxKeyEvent_GetUnicodeKey, "wxKeyEvent", "getUnicodeKey", 1}, // 2752
- {wxKeyEvent_GetX, "wxKeyEvent", "getX", 1}, // 2753
- {wxKeyEvent_GetY, "wxKeyEvent", "getY", 1}, // 2754
- {wxKeyEvent_HasModifiers, "wxKeyEvent", "hasModifiers", 1}, // 2755
- {wxKeyEvent_MetaDown, "wxKeyEvent", "metaDown", 1}, // 2756
- {wxKeyEvent_ShiftDown, "wxKeyEvent", "shiftDown", 1}, // 2757
- {wxSizeEvent_GetSize, "wxSizeEvent", "getSize", 1}, // 2758
- {wxSizeEvent_GetRect, "wxSizeEvent", "getRect", 1}, // 2759
- {wxMoveEvent_GetPosition, "wxMoveEvent", "getPosition", 1}, // 2760
- {wxMoveEvent_GetRect, "wxMoveEvent", "getRect", 1}, // 2761
- {wxEraseEvent_GetDC, "wxEraseEvent", "getDC", 1}, // 2762
- {wxFocusEvent_GetWindow, "wxFocusEvent", "getWindow", 1}, // 2763
- {wxChildFocusEvent_GetWindow, "wxChildFocusEvent", "getWindow", 1}, // 2764
- {wxMenuEvent_GetMenu, "wxMenuEvent", "getMenu", 1}, // 2765
- {wxMenuEvent_GetMenuId, "wxMenuEvent", "getMenuId", 1}, // 2766
- {wxMenuEvent_IsPopup, "wxMenuEvent", "isPopup", 1}, // 2767
- {wxCloseEvent_CanVeto, "wxCloseEvent", "canVeto", 1}, // 2768
- {wxCloseEvent_GetLoggingOff, "wxCloseEvent", "getLoggingOff", 1}, // 2769
- {wxCloseEvent_SetCanVeto, "wxCloseEvent", "setCanVeto", 2}, // 2770
- {wxCloseEvent_SetLoggingOff, "wxCloseEvent", "setLoggingOff", 2}, // 2771
- {wxCloseEvent_Veto, "wxCloseEvent", "veto", 2}, // 2772
- {wxShowEvent_SetShow, "wxShowEvent", "setShow", 2}, // 2773
- {wxShowEvent_IsShown, "wxShowEvent", "isShown", 1}, // 2774
- {wxIconizeEvent_IsIconized, "wxIconizeEvent", "isIconized", 1}, // 2775
- {wxJoystickEvent_ButtonDown, "wxJoystickEvent", "buttonDown", 2}, // 2776
- {wxJoystickEvent_ButtonIsDown, "wxJoystickEvent", "buttonIsDown", 2}, // 2777
- {wxJoystickEvent_ButtonUp, "wxJoystickEvent", "buttonUp", 2}, // 2778
- {wxJoystickEvent_GetButtonChange, "wxJoystickEvent", "getButtonChange", 1}, // 2779
- {wxJoystickEvent_GetButtonState, "wxJoystickEvent", "getButtonState", 1}, // 2780
- {wxJoystickEvent_GetJoystick, "wxJoystickEvent", "getJoystick", 1}, // 2781
- {wxJoystickEvent_GetPosition, "wxJoystickEvent", "getPosition", 1}, // 2782
- {wxJoystickEvent_GetZPosition, "wxJoystickEvent", "getZPosition", 1}, // 2783
- {wxJoystickEvent_IsButton, "wxJoystickEvent", "isButton", 1}, // 2784
- {wxJoystickEvent_IsMove, "wxJoystickEvent", "isMove", 1}, // 2785
- {wxJoystickEvent_IsZMove, "wxJoystickEvent", "isZMove", 1}, // 2786
- {wxUpdateUIEvent_CanUpdate, "wxUpdateUIEvent", "canUpdate", 1}, // 2787
- {wxUpdateUIEvent_Check, "wxUpdateUIEvent", "check", 2}, // 2788
- {wxUpdateUIEvent_Enable, "wxUpdateUIEvent", "enable", 2}, // 2789
- {wxUpdateUIEvent_Show, "wxUpdateUIEvent", "show", 2}, // 2790
- {wxUpdateUIEvent_GetChecked, "wxUpdateUIEvent", "getChecked", 1}, // 2791
- {wxUpdateUIEvent_GetEnabled, "wxUpdateUIEvent", "getEnabled", 1}, // 2792
- {wxUpdateUIEvent_GetShown, "wxUpdateUIEvent", "getShown", 1}, // 2793
- {wxUpdateUIEvent_GetSetChecked, "wxUpdateUIEvent", "getSetChecked", 1}, // 2794
- {wxUpdateUIEvent_GetSetEnabled, "wxUpdateUIEvent", "getSetEnabled", 1}, // 2795
- {wxUpdateUIEvent_GetSetShown, "wxUpdateUIEvent", "getSetShown", 1}, // 2796
- {wxUpdateUIEvent_GetSetText, "wxUpdateUIEvent", "getSetText", 1}, // 2797
- {wxUpdateUIEvent_GetText, "wxUpdateUIEvent", "getText", 1}, // 2798
- {wxUpdateUIEvent_GetMode, "wxUpdateUIEvent", "getMode", 0}, // 2799
- {wxUpdateUIEvent_GetUpdateInterval, "wxUpdateUIEvent", "getUpdateInterval", 0}, // 2800
- {wxUpdateUIEvent_ResetUpdateTime, "wxUpdateUIEvent", "resetUpdateTime", 0}, // 2801
- {wxUpdateUIEvent_SetMode, "wxUpdateUIEvent", "setMode", 1}, // 2802
- {wxUpdateUIEvent_SetText, "wxUpdateUIEvent", "setText", 2}, // 2803
- {wxUpdateUIEvent_SetUpdateInterval, "wxUpdateUIEvent", "setUpdateInterval", 1}, // 2804
- {wxMouseCaptureChangedEvent_GetCapturedWindow, "wxMouseCaptureChangedEvent", "getCapturedWindow", 1}, // 2805
- {wxPaletteChangedEvent_SetChangedWindow, "wxPaletteChangedEvent", "setChangedWindow", 2}, // 2806
- {wxPaletteChangedEvent_GetChangedWindow, "wxPaletteChangedEvent", "getChangedWindow", 1}, // 2807
- {wxQueryNewPaletteEvent_SetPaletteRealized, "wxQueryNewPaletteEvent", "setPaletteRealized", 2}, // 2808
- {wxQueryNewPaletteEvent_GetPaletteRealized, "wxQueryNewPaletteEvent", "getPaletteRealized", 1}, // 2809
- {wxNavigationKeyEvent_GetDirection, "wxNavigationKeyEvent", "getDirection", 1}, // 2810
- {wxNavigationKeyEvent_SetDirection, "wxNavigationKeyEvent", "setDirection", 2}, // 2811
- {wxNavigationKeyEvent_IsWindowChange, "wxNavigationKeyEvent", "isWindowChange", 1}, // 2812
- {wxNavigationKeyEvent_SetWindowChange, "wxNavigationKeyEvent", "setWindowChange", 2}, // 2813
- {wxNavigationKeyEvent_IsFromTab, "wxNavigationKeyEvent", "isFromTab", 1}, // 2814
- {wxNavigationKeyEvent_SetFromTab, "wxNavigationKeyEvent", "setFromTab", 2}, // 2815
- {wxNavigationKeyEvent_GetCurrentFocus, "wxNavigationKeyEvent", "getCurrentFocus", 1}, // 2816
- {wxNavigationKeyEvent_SetCurrentFocus, "wxNavigationKeyEvent", "setCurrentFocus", 2}, // 2817
- {wxHelpEvent_GetOrigin, "wxHelpEvent", "getOrigin", 1}, // 2818
- {wxHelpEvent_GetPosition, "wxHelpEvent", "getPosition", 1}, // 2819
- {wxHelpEvent_SetOrigin, "wxHelpEvent", "setOrigin", 2}, // 2820
- {wxHelpEvent_SetPosition, "wxHelpEvent", "setPosition", 2}, // 2821
- {wxContextMenuEvent_GetPosition, "wxContextMenuEvent", "getPosition", 1}, // 2822
- {wxContextMenuEvent_SetPosition, "wxContextMenuEvent", "setPosition", 2}, // 2823
- {wxIdleEvent_GetMode, "wxIdleEvent", "getMode", 0}, // 2824
- {wxIdleEvent_RequestMore, "wxIdleEvent", "requestMore", 2}, // 2825
- {wxIdleEvent_MoreRequested, "wxIdleEvent", "moreRequested", 1}, // 2826
- {wxIdleEvent_SetMode, "wxIdleEvent", "setMode", 1}, // 2827
- {wxGridEvent_AltDown, "wxGridEvent", "altDown", 1}, // 2828
- {wxGridEvent_ControlDown, "wxGridEvent", "controlDown", 1}, // 2829
- {wxGridEvent_GetCol, "wxGridEvent", "getCol", 1}, // 2830
- {wxGridEvent_GetPosition, "wxGridEvent", "getPosition", 1}, // 2831
- {wxGridEvent_GetRow, "wxGridEvent", "getRow", 1}, // 2832
- {wxGridEvent_MetaDown, "wxGridEvent", "metaDown", 1}, // 2833
- {wxGridEvent_Selecting, "wxGridEvent", "selecting", 1}, // 2834
- {wxGridEvent_ShiftDown, "wxGridEvent", "shiftDown", 1}, // 2835
- {wxNotifyEvent_Allow, "wxNotifyEvent", "allow", 1}, // 2836
- {wxNotifyEvent_IsAllowed, "wxNotifyEvent", "isAllowed", 1}, // 2837
- {wxNotifyEvent_Veto, "wxNotifyEvent", "veto", 1}, // 2838
- {wxSashEvent_GetEdge, "wxSashEvent", "getEdge", 1}, // 2839
- {wxSashEvent_GetDragRect, "wxSashEvent", "getDragRect", 1}, // 2840
- {wxSashEvent_GetDragStatus, "wxSashEvent", "getDragStatus", 1}, // 2841
- {wxListEvent_GetCacheFrom, "wxListEvent", "getCacheFrom", 1}, // 2842
- {wxListEvent_GetCacheTo, "wxListEvent", "getCacheTo", 1}, // 2843
- {wxListEvent_GetKeyCode, "wxListEvent", "getKeyCode", 1}, // 2844
- {wxListEvent_GetIndex, "wxListEvent", "getIndex", 1}, // 2845
- {wxListEvent_GetColumn, "wxListEvent", "getColumn", 1}, // 2846
- {wxListEvent_GetPoint, "wxListEvent", "getPoint", 1}, // 2847
- {wxListEvent_GetLabel, "wxListEvent", "getLabel", 1}, // 2848
- {wxListEvent_GetText, "wxListEvent", "getText", 1}, // 2849
- {wxListEvent_GetImage, "wxListEvent", "getImage", 1}, // 2850
- {wxListEvent_GetData, "wxListEvent", "getData", 1}, // 2851
- {wxListEvent_GetMask, "wxListEvent", "getMask", 1}, // 2852
- {wxListEvent_GetItem, "wxListEvent", "getItem", 1}, // 2853
- {wxListEvent_IsEditCancelled, "wxListEvent", "isEditCancelled", 1}, // 2854
- {wxDateEvent_GetDate, "wxDateEvent", "getDate", 1}, // 2855
- {wxCalendarEvent_GetWeekDay, "wxCalendarEvent", "getWeekDay", 1}, // 2856
- {wxCalendarEvent_GetDate, "wxCalendarEvent", "getDate", 1}, // 2857
- {wxFileDirPickerEvent_GetPath, "wxFileDirPickerEvent", "getPath", 1}, // 2858
- {wxColourPickerEvent_GetColour, "wxColourPickerEvent", "getColour", 1}, // 2859
- {wxFontPickerEvent_GetFont, "wxFontPickerEvent", "getFont", 1}, // 2860
- {wxStyledTextEvent_GetPosition, "wxStyledTextEvent", "getPosition", 1}, // 2861
- {wxStyledTextEvent_GetKey, "wxStyledTextEvent", "getKey", 1}, // 2862
- {wxStyledTextEvent_GetModifiers, "wxStyledTextEvent", "getModifiers", 1}, // 2863
- {wxStyledTextEvent_GetModificationType, "wxStyledTextEvent", "getModificationType", 1}, // 2864
- {wxStyledTextEvent_GetText, "wxStyledTextEvent", "getText", 1}, // 2865
- {wxStyledTextEvent_GetLength, "wxStyledTextEvent", "getLength", 1}, // 2866
- {wxStyledTextEvent_GetLinesAdded, "wxStyledTextEvent", "getLinesAdded", 1}, // 2867
- {wxStyledTextEvent_GetLine, "wxStyledTextEvent", "getLine", 1}, // 2868
- {wxStyledTextEvent_GetFoldLevelNow, "wxStyledTextEvent", "getFoldLevelNow", 1}, // 2869
- {wxStyledTextEvent_GetFoldLevelPrev, "wxStyledTextEvent", "getFoldLevelPrev", 1}, // 2870
- {wxStyledTextEvent_GetMargin, "wxStyledTextEvent", "getMargin", 1}, // 2871
- {wxStyledTextEvent_GetMessage, "wxStyledTextEvent", "getMessage", 1}, // 2872
- {wxStyledTextEvent_GetWParam, "wxStyledTextEvent", "getWParam", 1}, // 2873
- {wxStyledTextEvent_GetLParam, "wxStyledTextEvent", "getLParam", 1}, // 2874
- {wxStyledTextEvent_GetListType, "wxStyledTextEvent", "getListType", 1}, // 2875
- {wxStyledTextEvent_GetX, "wxStyledTextEvent", "getX", 1}, // 2876
- {wxStyledTextEvent_GetY, "wxStyledTextEvent", "getY", 1}, // 2877
- {wxStyledTextEvent_GetDragText, "wxStyledTextEvent", "getDragText", 1}, // 2878
- {wxStyledTextEvent_GetDragAllowMove, "wxStyledTextEvent", "getDragAllowMove", 1}, // 2879
- {wxStyledTextEvent_GetDragResult, "wxStyledTextEvent", "getDragResult", 1}, // 2880
- {wxStyledTextEvent_GetShift, "wxStyledTextEvent", "getShift", 1}, // 2881
- {wxStyledTextEvent_GetControl, "wxStyledTextEvent", "getControl", 1}, // 2882
- {wxStyledTextEvent_GetAlt, "wxStyledTextEvent", "getAlt", 1}, // 2883
- {utils_wxGetKeyState, "utils", "getKeyState", 1}, // 2884
- {utils_wxGetMousePosition, "utils", "getMousePosition", 0}, // 2885
- {utils_wxGetMouseState, "utils", "getMouseState", 0}, // 2886
- {utils_wxSetDetectableAutoRepeat, "utils", "setDetectableAutoRepeat", 1}, // 2887
- {utils_wxBell, "utils", "bell", 0}, // 2888
- {utils_wxFindMenuItemId, "utils", "findMenuItemId", 3}, // 2889
- {utils_wxFindWindowAtPoint, "utils", "findWindowAtPoint", 1}, // 2890
- {utils_wxBeginBusyCursor, "utils", "beginBusyCursor", 1}, // 2891
- {utils_wxEndBusyCursor, "utils", "endBusyCursor", 0}, // 2892
- {utils_wxIsBusy, "utils", "isBusy", 0}, // 2893
- {utils_wxShutdown, "utils", "shutdown", 1}, // 2894
- {utils_wxShell, "utils", "shell", 1}, // 2895
- {utils_wxLaunchDefaultBrowser, "utils", "launchDefaultBrowser", 2}, // 2896
- {utils_wxGetEmailAddress, "utils", "getEmailAddress", 0}, // 2897
- {utils_wxGetUserId, "utils", "getUserId", 0}, // 2898
- {utils_wxGetHomeDir, "utils", "getHomeDir", 0}, // 2899
- {utils_wxNewId, "utils", "newId", 0}, // 2900
- {utils_wxRegisterId, "utils", "registerId", 1}, // 2901
- {utils_wxGetCurrentId, "utils", "getCurrentId", 0}, // 2902
- {utils_wxGetOsDescription, "utils", "getOsDescription", 0}, // 2903
- {utils_wxIsPlatformLittleEndian, "utils", "isPlatformLittleEndian", 0}, // 2904
- {utils_wxIsPlatform64Bit, "utils", "isPlatform64Bit", 0}, // 2905
- {gdicmn_wxDisplaySize, "gdicmn", "displaySize", 0}, // 2906
- {gdicmn_wxSetCursor, "gdicmn", "setCursor", 1}, // 2907
- {wxPrintout_new, "wxPrintout", "new", 3}, // 2908
- {NULL, "wxPrintout", "destroy", 1}, // 2909 obj destructor wxPrintout_destruct
- {wxPrintout_GetDC, "wxPrintout", "getDC", 1}, // 2910
- {wxPrintout_GetPageSizeMM, "wxPrintout", "getPageSizeMM", 1}, // 2911
- {wxPrintout_GetPageSizePixels, "wxPrintout", "getPageSizePixels", 1}, // 2912
- {wxPrintout_GetPaperRectPixels, "wxPrintout", "getPaperRectPixels", 1}, // 2913
- {wxPrintout_GetPPIPrinter, "wxPrintout", "getPPIPrinter", 1}, // 2914
- {wxPrintout_GetPPIScreen, "wxPrintout", "getPPIScreen", 1}, // 2915
- {wxPrintout_GetTitle, "wxPrintout", "getTitle", 1}, // 2916
- {wxPrintout_IsPreview, "wxPrintout", "isPreview", 1}, // 2917
- {wxPrintout_FitThisSizeToPaper, "wxPrintout", "fitThisSizeToPaper", 2}, // 2918
- {wxPrintout_FitThisSizeToPage, "wxPrintout", "fitThisSizeToPage", 2}, // 2919
- {wxPrintout_FitThisSizeToPageMargins, "wxPrintout", "fitThisSizeToPageMargins", 3}, // 2920
- {wxPrintout_MapScreenSizeToPaper, "wxPrintout", "mapScreenSizeToPaper", 1}, // 2921
- {wxPrintout_MapScreenSizeToPage, "wxPrintout", "mapScreenSizeToPage", 1}, // 2922
- {wxPrintout_MapScreenSizeToPageMargins, "wxPrintout", "mapScreenSizeToPageMargins", 2}, // 2923
- {wxPrintout_MapScreenSizeToDevice, "wxPrintout", "mapScreenSizeToDevice", 1}, // 2924
- {wxPrintout_GetLogicalPaperRect, "wxPrintout", "getLogicalPaperRect", 1}, // 2925
- {wxPrintout_GetLogicalPageRect, "wxPrintout", "getLogicalPageRect", 1}, // 2926
- {wxPrintout_GetLogicalPageMarginsRect, "wxPrintout", "getLogicalPageMarginsRect", 2}, // 2927
- {wxPrintout_SetLogicalOrigin, "wxPrintout", "setLogicalOrigin", 3}, // 2928
- {wxPrintout_OffsetLogicalOrigin, "wxPrintout", "offsetLogicalOrigin", 3}, // 2929
- {wxStyledTextCtrl_new_2, "wxStyledTextCtrl", "new", 2}, // 2930
- {wxStyledTextCtrl_new_0, "wxStyledTextCtrl", "new", 0}, // 2931
- {NULL, "wxStyledTextCtrl", "destroy", 1}, // 2932 obj destructor wxStyledTextCtrl_destruct
- {wxStyledTextCtrl_Create, "wxStyledTextCtrl", "create", 3}, // 2933
- {wxStyledTextCtrl_AddText, "wxStyledTextCtrl", "addText", 2}, // 2934
- {wxStyledTextCtrl_InsertText, "wxStyledTextCtrl", "insertText", 3}, // 2935
- {wxStyledTextCtrl_ClearAll, "wxStyledTextCtrl", "clearAll", 1}, // 2936
- {wxStyledTextCtrl_ClearDocumentStyle, "wxStyledTextCtrl", "clearDocumentStyle", 1}, // 2937
- {wxStyledTextCtrl_GetLength, "wxStyledTextCtrl", "getLength", 1}, // 2938
- {wxStyledTextCtrl_GetCharAt, "wxStyledTextCtrl", "getCharAt", 2}, // 2939
- {wxStyledTextCtrl_GetCurrentPos, "wxStyledTextCtrl", "getCurrentPos", 1}, // 2940
- {wxStyledTextCtrl_GetAnchor, "wxStyledTextCtrl", "getAnchor", 1}, // 2941
- {wxStyledTextCtrl_GetStyleAt, "wxStyledTextCtrl", "getStyleAt", 2}, // 2942
- {wxStyledTextCtrl_Redo, "wxStyledTextCtrl", "redo", 1}, // 2943
- {wxStyledTextCtrl_SetUndoCollection, "wxStyledTextCtrl", "setUndoCollection", 2}, // 2944
- {wxStyledTextCtrl_SelectAll, "wxStyledTextCtrl", "selectAll", 1}, // 2945
- {wxStyledTextCtrl_SetSavePoint, "wxStyledTextCtrl", "setSavePoint", 1}, // 2946
- {wxStyledTextCtrl_CanRedo, "wxStyledTextCtrl", "canRedo", 1}, // 2947
- {wxStyledTextCtrl_MarkerLineFromHandle, "wxStyledTextCtrl", "markerLineFromHandle", 2}, // 2948
- {wxStyledTextCtrl_MarkerDeleteHandle, "wxStyledTextCtrl", "markerDeleteHandle", 2}, // 2949
- {wxStyledTextCtrl_GetUndoCollection, "wxStyledTextCtrl", "getUndoCollection", 1}, // 2950
- {wxStyledTextCtrl_GetViewWhiteSpace, "wxStyledTextCtrl", "getViewWhiteSpace", 1}, // 2951
- {wxStyledTextCtrl_SetViewWhiteSpace, "wxStyledTextCtrl", "setViewWhiteSpace", 2}, // 2952
- {wxStyledTextCtrl_PositionFromPoint, "wxStyledTextCtrl", "positionFromPoint", 2}, // 2953
- {wxStyledTextCtrl_PositionFromPointClose, "wxStyledTextCtrl", "positionFromPointClose", 3}, // 2954
- {wxStyledTextCtrl_GotoLine, "wxStyledTextCtrl", "gotoLine", 2}, // 2955
- {wxStyledTextCtrl_GotoPos, "wxStyledTextCtrl", "gotoPos", 2}, // 2956
- {wxStyledTextCtrl_SetAnchor, "wxStyledTextCtrl", "setAnchor", 2}, // 2957
- {wxStyledTextCtrl_GetCurLine, "wxStyledTextCtrl", "getCurLine", 1}, // 2958
- {wxStyledTextCtrl_GetEndStyled, "wxStyledTextCtrl", "getEndStyled", 1}, // 2959
- {wxStyledTextCtrl_ConvertEOLs, "wxStyledTextCtrl", "convertEOLs", 2}, // 2960
- {wxStyledTextCtrl_GetEOLMode, "wxStyledTextCtrl", "getEOLMode", 1}, // 2961
- {wxStyledTextCtrl_SetEOLMode, "wxStyledTextCtrl", "setEOLMode", 2}, // 2962
- {wxStyledTextCtrl_StartStyling, "wxStyledTextCtrl", "startStyling", 2}, // 2963
- {wxStyledTextCtrl_SetStyling, "wxStyledTextCtrl", "setStyling", 3}, // 2964
- {wxStyledTextCtrl_GetBufferedDraw, "wxStyledTextCtrl", "getBufferedDraw", 1}, // 2965
- {wxStyledTextCtrl_SetBufferedDraw, "wxStyledTextCtrl", "setBufferedDraw", 2}, // 2966
- {wxStyledTextCtrl_SetTabWidth, "wxStyledTextCtrl", "setTabWidth", 2}, // 2967
- {wxStyledTextCtrl_GetTabWidth, "wxStyledTextCtrl", "getTabWidth", 1}, // 2968
- {wxStyledTextCtrl_SetCodePage, "wxStyledTextCtrl", "setCodePage", 2}, // 2969
- {wxStyledTextCtrl_MarkerDefine, "wxStyledTextCtrl", "markerDefine", 4}, // 2970
- {wxStyledTextCtrl_MarkerSetForeground, "wxStyledTextCtrl", "markerSetForeground", 3}, // 2971
- {wxStyledTextCtrl_MarkerSetBackground, "wxStyledTextCtrl", "markerSetBackground", 3}, // 2972
- {wxStyledTextCtrl_MarkerAdd, "wxStyledTextCtrl", "markerAdd", 3}, // 2973
- {wxStyledTextCtrl_MarkerDelete, "wxStyledTextCtrl", "markerDelete", 3}, // 2974
- {wxStyledTextCtrl_MarkerDeleteAll, "wxStyledTextCtrl", "markerDeleteAll", 2}, // 2975
- {wxStyledTextCtrl_MarkerGet, "wxStyledTextCtrl", "markerGet", 2}, // 2976
- {wxStyledTextCtrl_MarkerNext, "wxStyledTextCtrl", "markerNext", 3}, // 2977
- {wxStyledTextCtrl_MarkerPrevious, "wxStyledTextCtrl", "markerPrevious", 3}, // 2978
- {wxStyledTextCtrl_MarkerDefineBitmap, "wxStyledTextCtrl", "markerDefineBitmap", 3}, // 2979
- {wxStyledTextCtrl_MarkerAddSet, "wxStyledTextCtrl", "markerAddSet", 3}, // 2980
- {wxStyledTextCtrl_MarkerSetAlpha, "wxStyledTextCtrl", "markerSetAlpha", 3}, // 2981
- {wxStyledTextCtrl_SetMarginType, "wxStyledTextCtrl", "setMarginType", 3}, // 2982
- {wxStyledTextCtrl_GetMarginType, "wxStyledTextCtrl", "getMarginType", 2}, // 2983
- {wxStyledTextCtrl_SetMarginWidth, "wxStyledTextCtrl", "setMarginWidth", 3}, // 2984
- {wxStyledTextCtrl_GetMarginWidth, "wxStyledTextCtrl", "getMarginWidth", 2}, // 2985
- {wxStyledTextCtrl_SetMarginMask, "wxStyledTextCtrl", "setMarginMask", 3}, // 2986
- {wxStyledTextCtrl_GetMarginMask, "wxStyledTextCtrl", "getMarginMask", 2}, // 2987
- {wxStyledTextCtrl_SetMarginSensitive, "wxStyledTextCtrl", "setMarginSensitive", 3}, // 2988
- {wxStyledTextCtrl_GetMarginSensitive, "wxStyledTextCtrl", "getMarginSensitive", 2}, // 2989
- {wxStyledTextCtrl_StyleClearAll, "wxStyledTextCtrl", "styleClearAll", 1}, // 2990
- {wxStyledTextCtrl_StyleSetForeground, "wxStyledTextCtrl", "styleSetForeground", 3}, // 2991
- {wxStyledTextCtrl_StyleSetBackground, "wxStyledTextCtrl", "styleSetBackground", 3}, // 2992
- {wxStyledTextCtrl_StyleSetBold, "wxStyledTextCtrl", "styleSetBold", 3}, // 2993
- {wxStyledTextCtrl_StyleSetItalic, "wxStyledTextCtrl", "styleSetItalic", 3}, // 2994
- {wxStyledTextCtrl_StyleSetSize, "wxStyledTextCtrl", "styleSetSize", 3}, // 2995
- {wxStyledTextCtrl_StyleSetFaceName, "wxStyledTextCtrl", "styleSetFaceName", 3}, // 2996
- {wxStyledTextCtrl_StyleSetEOLFilled, "wxStyledTextCtrl", "styleSetEOLFilled", 3}, // 2997
- {wxStyledTextCtrl_StyleResetDefault, "wxStyledTextCtrl", "styleResetDefault", 1}, // 2998
- {wxStyledTextCtrl_StyleSetUnderline, "wxStyledTextCtrl", "styleSetUnderline", 3}, // 2999
- {wxStyledTextCtrl_StyleSetCase, "wxStyledTextCtrl", "styleSetCase", 3}, // 3000
- {wxStyledTextCtrl_StyleSetHotSpot, "wxStyledTextCtrl", "styleSetHotSpot", 3}, // 3001
- {wxStyledTextCtrl_SetSelForeground, "wxStyledTextCtrl", "setSelForeground", 3}, // 3002
- {wxStyledTextCtrl_SetSelBackground, "wxStyledTextCtrl", "setSelBackground", 3}, // 3003
- {wxStyledTextCtrl_GetSelAlpha, "wxStyledTextCtrl", "getSelAlpha", 1}, // 3004
- {wxStyledTextCtrl_SetSelAlpha, "wxStyledTextCtrl", "setSelAlpha", 2}, // 3005
- {wxStyledTextCtrl_SetCaretForeground, "wxStyledTextCtrl", "setCaretForeground", 2}, // 3006
- {wxStyledTextCtrl_CmdKeyAssign, "wxStyledTextCtrl", "cmdKeyAssign", 4}, // 3007
- {wxStyledTextCtrl_CmdKeyClear, "wxStyledTextCtrl", "cmdKeyClear", 3}, // 3008
- {wxStyledTextCtrl_CmdKeyClearAll, "wxStyledTextCtrl", "cmdKeyClearAll", 1}, // 3009
- {wxStyledTextCtrl_SetStyleBytes, "wxStyledTextCtrl", "setStyleBytes", 2}, // 3010
- {wxStyledTextCtrl_StyleSetVisible, "wxStyledTextCtrl", "styleSetVisible", 3}, // 3011
- {wxStyledTextCtrl_GetCaretPeriod, "wxStyledTextCtrl", "getCaretPeriod", 1}, // 3012
- {wxStyledTextCtrl_SetCaretPeriod, "wxStyledTextCtrl", "setCaretPeriod", 2}, // 3013
- {wxStyledTextCtrl_SetWordChars, "wxStyledTextCtrl", "setWordChars", 2}, // 3014
- {wxStyledTextCtrl_BeginUndoAction, "wxStyledTextCtrl", "beginUndoAction", 1}, // 3015
- {wxStyledTextCtrl_EndUndoAction, "wxStyledTextCtrl", "endUndoAction", 1}, // 3016
- {wxStyledTextCtrl_IndicatorSetStyle, "wxStyledTextCtrl", "indicatorSetStyle", 3}, // 3017
- {wxStyledTextCtrl_IndicatorGetStyle, "wxStyledTextCtrl", "indicatorGetStyle", 2}, // 3018
- {wxStyledTextCtrl_IndicatorSetForeground, "wxStyledTextCtrl", "indicatorSetForeground", 3}, // 3019
- {wxStyledTextCtrl_IndicatorGetForeground, "wxStyledTextCtrl", "indicatorGetForeground", 2}, // 3020
- {wxStyledTextCtrl_SetWhitespaceForeground, "wxStyledTextCtrl", "setWhitespaceForeground", 3}, // 3021
- {wxStyledTextCtrl_SetWhitespaceBackground, "wxStyledTextCtrl", "setWhitespaceBackground", 3}, // 3022
- {wxStyledTextCtrl_GetStyleBits, "wxStyledTextCtrl", "getStyleBits", 1}, // 3023
- {wxStyledTextCtrl_SetLineState, "wxStyledTextCtrl", "setLineState", 3}, // 3024
- {wxStyledTextCtrl_GetLineState, "wxStyledTextCtrl", "getLineState", 2}, // 3025
- {wxStyledTextCtrl_GetMaxLineState, "wxStyledTextCtrl", "getMaxLineState", 1}, // 3026
- {wxStyledTextCtrl_GetCaretLineVisible, "wxStyledTextCtrl", "getCaretLineVisible", 1}, // 3027
- {wxStyledTextCtrl_SetCaretLineVisible, "wxStyledTextCtrl", "setCaretLineVisible", 2}, // 3028
- {wxStyledTextCtrl_GetCaretLineBackground, "wxStyledTextCtrl", "getCaretLineBackground", 1}, // 3029
- {wxStyledTextCtrl_SetCaretLineBackground, "wxStyledTextCtrl", "setCaretLineBackground", 2}, // 3030
- {wxStyledTextCtrl_AutoCompShow, "wxStyledTextCtrl", "autoCompShow", 3}, // 3031
- {wxStyledTextCtrl_AutoCompCancel, "wxStyledTextCtrl", "autoCompCancel", 1}, // 3032
- {wxStyledTextCtrl_AutoCompActive, "wxStyledTextCtrl", "autoCompActive", 1}, // 3033
- {wxStyledTextCtrl_AutoCompPosStart, "wxStyledTextCtrl", "autoCompPosStart", 1}, // 3034
- {wxStyledTextCtrl_AutoCompComplete, "wxStyledTextCtrl", "autoCompComplete", 1}, // 3035
- {wxStyledTextCtrl_AutoCompStops, "wxStyledTextCtrl", "autoCompStops", 2}, // 3036
- {wxStyledTextCtrl_AutoCompSetSeparator, "wxStyledTextCtrl", "autoCompSetSeparator", 2}, // 3037
- {wxStyledTextCtrl_AutoCompGetSeparator, "wxStyledTextCtrl", "autoCompGetSeparator", 1}, // 3038
- {wxStyledTextCtrl_AutoCompSelect, "wxStyledTextCtrl", "autoCompSelect", 2}, // 3039
- {wxStyledTextCtrl_AutoCompSetCancelAtStart, "wxStyledTextCtrl", "autoCompSetCancelAtStart", 2}, // 3040
- {wxStyledTextCtrl_AutoCompGetCancelAtStart, "wxStyledTextCtrl", "autoCompGetCancelAtStart", 1}, // 3041
- {wxStyledTextCtrl_AutoCompSetFillUps, "wxStyledTextCtrl", "autoCompSetFillUps", 2}, // 3042
- {wxStyledTextCtrl_AutoCompSetChooseSingle, "wxStyledTextCtrl", "autoCompSetChooseSingle", 2}, // 3043
- {wxStyledTextCtrl_AutoCompGetChooseSingle, "wxStyledTextCtrl", "autoCompGetChooseSingle", 1}, // 3044
- {wxStyledTextCtrl_AutoCompSetIgnoreCase, "wxStyledTextCtrl", "autoCompSetIgnoreCase", 2}, // 3045
- {wxStyledTextCtrl_AutoCompGetIgnoreCase, "wxStyledTextCtrl", "autoCompGetIgnoreCase", 1}, // 3046
- {wxStyledTextCtrl_UserListShow, "wxStyledTextCtrl", "userListShow", 3}, // 3047
- {wxStyledTextCtrl_AutoCompSetAutoHide, "wxStyledTextCtrl", "autoCompSetAutoHide", 2}, // 3048
- {wxStyledTextCtrl_AutoCompGetAutoHide, "wxStyledTextCtrl", "autoCompGetAutoHide", 1}, // 3049
- {wxStyledTextCtrl_AutoCompSetDropRestOfWord, "wxStyledTextCtrl", "autoCompSetDropRestOfWord", 2}, // 3050
- {wxStyledTextCtrl_AutoCompGetDropRestOfWord, "wxStyledTextCtrl", "autoCompGetDropRestOfWord", 1}, // 3051
- {wxStyledTextCtrl_RegisterImage, "wxStyledTextCtrl", "registerImage", 3}, // 3052
- {wxStyledTextCtrl_ClearRegisteredImages, "wxStyledTextCtrl", "clearRegisteredImages", 1}, // 3053
- {wxStyledTextCtrl_AutoCompGetTypeSeparator, "wxStyledTextCtrl", "autoCompGetTypeSeparator", 1}, // 3054
- {wxStyledTextCtrl_AutoCompSetTypeSeparator, "wxStyledTextCtrl", "autoCompSetTypeSeparator", 2}, // 3055
- {wxStyledTextCtrl_AutoCompSetMaxWidth, "wxStyledTextCtrl", "autoCompSetMaxWidth", 2}, // 3056
- {wxStyledTextCtrl_AutoCompGetMaxWidth, "wxStyledTextCtrl", "autoCompGetMaxWidth", 1}, // 3057
- {wxStyledTextCtrl_AutoCompSetMaxHeight, "wxStyledTextCtrl", "autoCompSetMaxHeight", 2}, // 3058
- {wxStyledTextCtrl_AutoCompGetMaxHeight, "wxStyledTextCtrl", "autoCompGetMaxHeight", 1}, // 3059
- {wxStyledTextCtrl_SetIndent, "wxStyledTextCtrl", "setIndent", 2}, // 3060
- {wxStyledTextCtrl_GetIndent, "wxStyledTextCtrl", "getIndent", 1}, // 3061
- {wxStyledTextCtrl_SetUseTabs, "wxStyledTextCtrl", "setUseTabs", 2}, // 3062
- {wxStyledTextCtrl_GetUseTabs, "wxStyledTextCtrl", "getUseTabs", 1}, // 3063
- {wxStyledTextCtrl_SetLineIndentation, "wxStyledTextCtrl", "setLineIndentation", 3}, // 3064
- {wxStyledTextCtrl_GetLineIndentation, "wxStyledTextCtrl", "getLineIndentation", 2}, // 3065
- {wxStyledTextCtrl_GetLineIndentPosition, "wxStyledTextCtrl", "getLineIndentPosition", 2}, // 3066
- {wxStyledTextCtrl_GetColumn, "wxStyledTextCtrl", "getColumn", 2}, // 3067
- {wxStyledTextCtrl_SetUseHorizontalScrollBar, "wxStyledTextCtrl", "setUseHorizontalScrollBar", 2}, // 3068
- {wxStyledTextCtrl_GetUseHorizontalScrollBar, "wxStyledTextCtrl", "getUseHorizontalScrollBar", 1}, // 3069
- {wxStyledTextCtrl_SetIndentationGuides, "wxStyledTextCtrl", "setIndentationGuides", 2}, // 3070
- {wxStyledTextCtrl_GetIndentationGuides, "wxStyledTextCtrl", "getIndentationGuides", 1}, // 3071
- {wxStyledTextCtrl_SetHighlightGuide, "wxStyledTextCtrl", "setHighlightGuide", 2}, // 3072
- {wxStyledTextCtrl_GetHighlightGuide, "wxStyledTextCtrl", "getHighlightGuide", 1}, // 3073
- {wxStyledTextCtrl_GetLineEndPosition, "wxStyledTextCtrl", "getLineEndPosition", 2}, // 3074
- {wxStyledTextCtrl_GetCodePage, "wxStyledTextCtrl", "getCodePage", 1}, // 3075
- {wxStyledTextCtrl_GetCaretForeground, "wxStyledTextCtrl", "getCaretForeground", 1}, // 3076
- {wxStyledTextCtrl_GetReadOnly, "wxStyledTextCtrl", "getReadOnly", 1}, // 3077
- {wxStyledTextCtrl_SetCurrentPos, "wxStyledTextCtrl", "setCurrentPos", 2}, // 3078
- {wxStyledTextCtrl_SetSelectionStart, "wxStyledTextCtrl", "setSelectionStart", 2}, // 3079
- {wxStyledTextCtrl_GetSelectionStart, "wxStyledTextCtrl", "getSelectionStart", 1}, // 3080
- {wxStyledTextCtrl_SetSelectionEnd, "wxStyledTextCtrl", "setSelectionEnd", 2}, // 3081
- {wxStyledTextCtrl_GetSelectionEnd, "wxStyledTextCtrl", "getSelectionEnd", 1}, // 3082
- {wxStyledTextCtrl_SetPrintMagnification, "wxStyledTextCtrl", "setPrintMagnification", 2}, // 3083
- {wxStyledTextCtrl_GetPrintMagnification, "wxStyledTextCtrl", "getPrintMagnification", 1}, // 3084
- {wxStyledTextCtrl_SetPrintColourMode, "wxStyledTextCtrl", "setPrintColourMode", 2}, // 3085
- {wxStyledTextCtrl_GetPrintColourMode, "wxStyledTextCtrl", "getPrintColourMode", 1}, // 3086
- {wxStyledTextCtrl_FindText, "wxStyledTextCtrl", "findText", 5}, // 3087
- {wxStyledTextCtrl_FormatRange, "wxStyledTextCtrl", "formatRange", 8}, // 3088
- {wxStyledTextCtrl_GetFirstVisibleLine, "wxStyledTextCtrl", "getFirstVisibleLine", 1}, // 3089
- {wxStyledTextCtrl_GetLine, "wxStyledTextCtrl", "getLine", 2}, // 3090
- {wxStyledTextCtrl_GetLineCount, "wxStyledTextCtrl", "getLineCount", 1}, // 3091
- {wxStyledTextCtrl_SetMarginLeft, "wxStyledTextCtrl", "setMarginLeft", 2}, // 3092
- {wxStyledTextCtrl_GetMarginLeft, "wxStyledTextCtrl", "getMarginLeft", 1}, // 3093
- {wxStyledTextCtrl_SetMarginRight, "wxStyledTextCtrl", "setMarginRight", 2}, // 3094
- {wxStyledTextCtrl_GetMarginRight, "wxStyledTextCtrl", "getMarginRight", 1}, // 3095
- {wxStyledTextCtrl_GetModify, "wxStyledTextCtrl", "getModify", 1}, // 3096
- {wxStyledTextCtrl_SetSelection, "wxStyledTextCtrl", "setSelection", 3}, // 3097
- {wxStyledTextCtrl_GetSelectedText, "wxStyledTextCtrl", "getSelectedText", 1}, // 3098
- {wxStyledTextCtrl_GetTextRange, "wxStyledTextCtrl", "getTextRange", 3}, // 3099
- {wxStyledTextCtrl_HideSelection, "wxStyledTextCtrl", "hideSelection", 2}, // 3100
- {wxStyledTextCtrl_LineFromPosition, "wxStyledTextCtrl", "lineFromPosition", 2}, // 3101
- {wxStyledTextCtrl_PositionFromLine, "wxStyledTextCtrl", "positionFromLine", 2}, // 3102
- {wxStyledTextCtrl_LineScroll, "wxStyledTextCtrl", "lineScroll", 3}, // 3103
- {wxStyledTextCtrl_EnsureCaretVisible, "wxStyledTextCtrl", "ensureCaretVisible", 1}, // 3104
- {wxStyledTextCtrl_ReplaceSelection, "wxStyledTextCtrl", "replaceSelection", 2}, // 3105
- {wxStyledTextCtrl_SetReadOnly, "wxStyledTextCtrl", "setReadOnly", 2}, // 3106
- {wxStyledTextCtrl_CanPaste, "wxStyledTextCtrl", "canPaste", 1}, // 3107
- {wxStyledTextCtrl_CanUndo, "wxStyledTextCtrl", "canUndo", 1}, // 3108
- {wxStyledTextCtrl_EmptyUndoBuffer, "wxStyledTextCtrl", "emptyUndoBuffer", 1}, // 3109
- {wxStyledTextCtrl_Undo, "wxStyledTextCtrl", "undo", 1}, // 3110
- {wxStyledTextCtrl_Cut, "wxStyledTextCtrl", "cut", 1}, // 3111
- {wxStyledTextCtrl_Copy, "wxStyledTextCtrl", "copy", 1}, // 3112
- {wxStyledTextCtrl_Paste, "wxStyledTextCtrl", "paste", 1}, // 3113
- {wxStyledTextCtrl_Clear, "wxStyledTextCtrl", "clear", 1}, // 3114
- {wxStyledTextCtrl_SetText, "wxStyledTextCtrl", "setText", 2}, // 3115
- {wxStyledTextCtrl_GetText, "wxStyledTextCtrl", "getText", 1}, // 3116
- {wxStyledTextCtrl_GetTextLength, "wxStyledTextCtrl", "getTextLength", 1}, // 3117
- {wxStyledTextCtrl_GetOvertype, "wxStyledTextCtrl", "getOvertype", 1}, // 3118
- {wxStyledTextCtrl_SetCaretWidth, "wxStyledTextCtrl", "setCaretWidth", 2}, // 3119
- {wxStyledTextCtrl_GetCaretWidth, "wxStyledTextCtrl", "getCaretWidth", 1}, // 3120
- {wxStyledTextCtrl_SetTargetStart, "wxStyledTextCtrl", "setTargetStart", 2}, // 3121
- {wxStyledTextCtrl_GetTargetStart, "wxStyledTextCtrl", "getTargetStart", 1}, // 3122
- {wxStyledTextCtrl_SetTargetEnd, "wxStyledTextCtrl", "setTargetEnd", 2}, // 3123
- {wxStyledTextCtrl_GetTargetEnd, "wxStyledTextCtrl", "getTargetEnd", 1}, // 3124
- {wxStyledTextCtrl_ReplaceTarget, "wxStyledTextCtrl", "replaceTarget", 2}, // 3125
- {wxStyledTextCtrl_SearchInTarget, "wxStyledTextCtrl", "searchInTarget", 2}, // 3126
- {wxStyledTextCtrl_SetSearchFlags, "wxStyledTextCtrl", "setSearchFlags", 2}, // 3127
- {wxStyledTextCtrl_GetSearchFlags, "wxStyledTextCtrl", "getSearchFlags", 1}, // 3128
- {wxStyledTextCtrl_CallTipShow, "wxStyledTextCtrl", "callTipShow", 3}, // 3129
- {wxStyledTextCtrl_CallTipCancel, "wxStyledTextCtrl", "callTipCancel", 1}, // 3130
- {wxStyledTextCtrl_CallTipActive, "wxStyledTextCtrl", "callTipActive", 1}, // 3131
- {wxStyledTextCtrl_CallTipPosAtStart, "wxStyledTextCtrl", "callTipPosAtStart", 1}, // 3132
- {wxStyledTextCtrl_CallTipSetHighlight, "wxStyledTextCtrl", "callTipSetHighlight", 3}, // 3133
- {wxStyledTextCtrl_CallTipSetBackground, "wxStyledTextCtrl", "callTipSetBackground", 2}, // 3134
- {wxStyledTextCtrl_CallTipSetForeground, "wxStyledTextCtrl", "callTipSetForeground", 2}, // 3135
- {wxStyledTextCtrl_CallTipSetForegroundHighlight, "wxStyledTextCtrl", "callTipSetForegroundHighlight", 2}, // 3136
- {wxStyledTextCtrl_CallTipUseStyle, "wxStyledTextCtrl", "callTipUseStyle", 2}, // 3137
- {wxStyledTextCtrl_VisibleFromDocLine, "wxStyledTextCtrl", "visibleFromDocLine", 2}, // 3138
- {wxStyledTextCtrl_DocLineFromVisible, "wxStyledTextCtrl", "docLineFromVisible", 2}, // 3139
- {wxStyledTextCtrl_WrapCount, "wxStyledTextCtrl", "wrapCount", 2}, // 3140
- {wxStyledTextCtrl_SetFoldLevel, "wxStyledTextCtrl", "setFoldLevel", 3}, // 3141
- {wxStyledTextCtrl_GetFoldLevel, "wxStyledTextCtrl", "getFoldLevel", 2}, // 3142
- {wxStyledTextCtrl_GetLastChild, "wxStyledTextCtrl", "getLastChild", 3}, // 3143
- {wxStyledTextCtrl_GetFoldParent, "wxStyledTextCtrl", "getFoldParent", 2}, // 3144
- {wxStyledTextCtrl_ShowLines, "wxStyledTextCtrl", "showLines", 3}, // 3145
- {wxStyledTextCtrl_HideLines, "wxStyledTextCtrl", "hideLines", 3}, // 3146
- {wxStyledTextCtrl_GetLineVisible, "wxStyledTextCtrl", "getLineVisible", 2}, // 3147
- {wxStyledTextCtrl_SetFoldExpanded, "wxStyledTextCtrl", "setFoldExpanded", 3}, // 3148
- {wxStyledTextCtrl_GetFoldExpanded, "wxStyledTextCtrl", "getFoldExpanded", 2}, // 3149
- {wxStyledTextCtrl_ToggleFold, "wxStyledTextCtrl", "toggleFold", 2}, // 3150
- {wxStyledTextCtrl_EnsureVisible, "wxStyledTextCtrl", "ensureVisible", 2}, // 3151
- {wxStyledTextCtrl_SetFoldFlags, "wxStyledTextCtrl", "setFoldFlags", 2}, // 3152
- {wxStyledTextCtrl_EnsureVisibleEnforcePolicy, "wxStyledTextCtrl", "ensureVisibleEnforcePolicy", 2}, // 3153
- {wxStyledTextCtrl_SetTabIndents, "wxStyledTextCtrl", "setTabIndents", 2}, // 3154
- {wxStyledTextCtrl_GetTabIndents, "wxStyledTextCtrl", "getTabIndents", 1}, // 3155
- {wxStyledTextCtrl_SetBackSpaceUnIndents, "wxStyledTextCtrl", "setBackSpaceUnIndents", 2}, // 3156
- {wxStyledTextCtrl_GetBackSpaceUnIndents, "wxStyledTextCtrl", "getBackSpaceUnIndents", 1}, // 3157
- {wxStyledTextCtrl_SetMouseDwellTime, "wxStyledTextCtrl", "setMouseDwellTime", 2}, // 3158
- {wxStyledTextCtrl_GetMouseDwellTime, "wxStyledTextCtrl", "getMouseDwellTime", 1}, // 3159
- {wxStyledTextCtrl_WordStartPosition, "wxStyledTextCtrl", "wordStartPosition", 3}, // 3160
- {wxStyledTextCtrl_WordEndPosition, "wxStyledTextCtrl", "wordEndPosition", 3}, // 3161
- {wxStyledTextCtrl_SetWrapMode, "wxStyledTextCtrl", "setWrapMode", 2}, // 3162
- {wxStyledTextCtrl_GetWrapMode, "wxStyledTextCtrl", "getWrapMode", 1}, // 3163
- {wxStyledTextCtrl_SetWrapVisualFlags, "wxStyledTextCtrl", "setWrapVisualFlags", 2}, // 3164
- {wxStyledTextCtrl_GetWrapVisualFlags, "wxStyledTextCtrl", "getWrapVisualFlags", 1}, // 3165
- {wxStyledTextCtrl_SetWrapVisualFlagsLocation, "wxStyledTextCtrl", "setWrapVisualFlagsLocation", 2}, // 3166
- {wxStyledTextCtrl_GetWrapVisualFlagsLocation, "wxStyledTextCtrl", "getWrapVisualFlagsLocation", 1}, // 3167
- {wxStyledTextCtrl_SetWrapStartIndent, "wxStyledTextCtrl", "setWrapStartIndent", 2}, // 3168
- {wxStyledTextCtrl_GetWrapStartIndent, "wxStyledTextCtrl", "getWrapStartIndent", 1}, // 3169
- {wxStyledTextCtrl_SetLayoutCache, "wxStyledTextCtrl", "setLayoutCache", 2}, // 3170
- {wxStyledTextCtrl_GetLayoutCache, "wxStyledTextCtrl", "getLayoutCache", 1}, // 3171
- {wxStyledTextCtrl_SetScrollWidth, "wxStyledTextCtrl", "setScrollWidth", 2}, // 3172
- {wxStyledTextCtrl_GetScrollWidth, "wxStyledTextCtrl", "getScrollWidth", 1}, // 3173
- {wxStyledTextCtrl_TextWidth, "wxStyledTextCtrl", "textWidth", 3}, // 3174
- {wxStyledTextCtrl_GetEndAtLastLine, "wxStyledTextCtrl", "getEndAtLastLine", 1}, // 3175
- {wxStyledTextCtrl_TextHeight, "wxStyledTextCtrl", "textHeight", 2}, // 3176
- {wxStyledTextCtrl_SetUseVerticalScrollBar, "wxStyledTextCtrl", "setUseVerticalScrollBar", 2}, // 3177
- {wxStyledTextCtrl_GetUseVerticalScrollBar, "wxStyledTextCtrl", "getUseVerticalScrollBar", 1}, // 3178
- {wxStyledTextCtrl_AppendText, "wxStyledTextCtrl", "appendText", 2}, // 3179
- {wxStyledTextCtrl_GetTwoPhaseDraw, "wxStyledTextCtrl", "getTwoPhaseDraw", 1}, // 3180
- {wxStyledTextCtrl_SetTwoPhaseDraw, "wxStyledTextCtrl", "setTwoPhaseDraw", 2}, // 3181
- {wxStyledTextCtrl_TargetFromSelection, "wxStyledTextCtrl", "targetFromSelection", 1}, // 3182
- {wxStyledTextCtrl_LinesJoin, "wxStyledTextCtrl", "linesJoin", 1}, // 3183
- {wxStyledTextCtrl_LinesSplit, "wxStyledTextCtrl", "linesSplit", 2}, // 3184
- {wxStyledTextCtrl_SetFoldMarginColour, "wxStyledTextCtrl", "setFoldMarginColour", 3}, // 3185
- {wxStyledTextCtrl_SetFoldMarginHiColour, "wxStyledTextCtrl", "setFoldMarginHiColour", 3}, // 3186
- {wxStyledTextCtrl_LineDown, "wxStyledTextCtrl", "lineDown", 1}, // 3187
- {wxStyledTextCtrl_LineDownExtend, "wxStyledTextCtrl", "lineDownExtend", 1}, // 3188
- {wxStyledTextCtrl_LineUp, "wxStyledTextCtrl", "lineUp", 1}, // 3189
- {wxStyledTextCtrl_LineUpExtend, "wxStyledTextCtrl", "lineUpExtend", 1}, // 3190
- {wxStyledTextCtrl_CharLeft, "wxStyledTextCtrl", "charLeft", 1}, // 3191
- {wxStyledTextCtrl_CharLeftExtend, "wxStyledTextCtrl", "charLeftExtend", 1}, // 3192
- {wxStyledTextCtrl_CharRight, "wxStyledTextCtrl", "charRight", 1}, // 3193
- {wxStyledTextCtrl_CharRightExtend, "wxStyledTextCtrl", "charRightExtend", 1}, // 3194
- {wxStyledTextCtrl_WordLeft, "wxStyledTextCtrl", "wordLeft", 1}, // 3195
- {wxStyledTextCtrl_WordLeftExtend, "wxStyledTextCtrl", "wordLeftExtend", 1}, // 3196
- {wxStyledTextCtrl_WordRight, "wxStyledTextCtrl", "wordRight", 1}, // 3197
- {wxStyledTextCtrl_WordRightExtend, "wxStyledTextCtrl", "wordRightExtend", 1}, // 3198
- {wxStyledTextCtrl_Home, "wxStyledTextCtrl", "home", 1}, // 3199
- {wxStyledTextCtrl_HomeExtend, "wxStyledTextCtrl", "homeExtend", 1}, // 3200
- {wxStyledTextCtrl_LineEnd, "wxStyledTextCtrl", "lineEnd", 1}, // 3201
- {wxStyledTextCtrl_LineEndExtend, "wxStyledTextCtrl", "lineEndExtend", 1}, // 3202
- {wxStyledTextCtrl_DocumentStart, "wxStyledTextCtrl", "documentStart", 1}, // 3203
- {wxStyledTextCtrl_DocumentStartExtend, "wxStyledTextCtrl", "documentStartExtend", 1}, // 3204
- {wxStyledTextCtrl_DocumentEnd, "wxStyledTextCtrl", "documentEnd", 1}, // 3205
- {wxStyledTextCtrl_DocumentEndExtend, "wxStyledTextCtrl", "documentEndExtend", 1}, // 3206
- {wxStyledTextCtrl_PageUp, "wxStyledTextCtrl", "pageUp", 1}, // 3207
- {wxStyledTextCtrl_PageUpExtend, "wxStyledTextCtrl", "pageUpExtend", 1}, // 3208
- {wxStyledTextCtrl_PageDown, "wxStyledTextCtrl", "pageDown", 1}, // 3209
- {wxStyledTextCtrl_PageDownExtend, "wxStyledTextCtrl", "pageDownExtend", 1}, // 3210
- {wxStyledTextCtrl_EditToggleOvertype, "wxStyledTextCtrl", "editToggleOvertype", 1}, // 3211
- {wxStyledTextCtrl_Cancel, "wxStyledTextCtrl", "cancel", 1}, // 3212
- {wxStyledTextCtrl_DeleteBack, "wxStyledTextCtrl", "deleteBack", 1}, // 3213
- {wxStyledTextCtrl_Tab, "wxStyledTextCtrl", "tab", 1}, // 3214
- {wxStyledTextCtrl_BackTab, "wxStyledTextCtrl", "backTab", 1}, // 3215
- {wxStyledTextCtrl_NewLine, "wxStyledTextCtrl", "newLine", 1}, // 3216
- {wxStyledTextCtrl_FormFeed, "wxStyledTextCtrl", "formFeed", 1}, // 3217
- {wxStyledTextCtrl_VCHome, "wxStyledTextCtrl", "vCHome", 1}, // 3218
- {wxStyledTextCtrl_VCHomeExtend, "wxStyledTextCtrl", "vCHomeExtend", 1}, // 3219
- {wxStyledTextCtrl_ZoomIn, "wxStyledTextCtrl", "zoomIn", 1}, // 3220
- {wxStyledTextCtrl_ZoomOut, "wxStyledTextCtrl", "zoomOut", 1}, // 3221
- {wxStyledTextCtrl_DelWordLeft, "wxStyledTextCtrl", "delWordLeft", 1}, // 3222
- {wxStyledTextCtrl_DelWordRight, "wxStyledTextCtrl", "delWordRight", 1}, // 3223
- {wxStyledTextCtrl_LineCut, "wxStyledTextCtrl", "lineCut", 1}, // 3224
- {wxStyledTextCtrl_LineDelete, "wxStyledTextCtrl", "lineDelete", 1}, // 3225
- {wxStyledTextCtrl_LineTranspose, "wxStyledTextCtrl", "lineTranspose", 1}, // 3226
- {wxStyledTextCtrl_LineDuplicate, "wxStyledTextCtrl", "lineDuplicate", 1}, // 3227
- {wxStyledTextCtrl_LowerCase, "wxStyledTextCtrl", "lowerCase", 1}, // 3228
- {wxStyledTextCtrl_UpperCase, "wxStyledTextCtrl", "upperCase", 1}, // 3229
- {wxStyledTextCtrl_LineScrollDown, "wxStyledTextCtrl", "lineScrollDown", 1}, // 3230
- {wxStyledTextCtrl_LineScrollUp, "wxStyledTextCtrl", "lineScrollUp", 1}, // 3231
- {wxStyledTextCtrl_DeleteBackNotLine, "wxStyledTextCtrl", "deleteBackNotLine", 1}, // 3232
- {wxStyledTextCtrl_HomeDisplay, "wxStyledTextCtrl", "homeDisplay", 1}, // 3233
- {wxStyledTextCtrl_HomeDisplayExtend, "wxStyledTextCtrl", "homeDisplayExtend", 1}, // 3234
- {wxStyledTextCtrl_LineEndDisplay, "wxStyledTextCtrl", "lineEndDisplay", 1}, // 3235
- {wxStyledTextCtrl_LineEndDisplayExtend, "wxStyledTextCtrl", "lineEndDisplayExtend", 1}, // 3236
- {wxStyledTextCtrl_HomeWrapExtend, "wxStyledTextCtrl", "homeWrapExtend", 1}, // 3237
- {wxStyledTextCtrl_LineEndWrap, "wxStyledTextCtrl", "lineEndWrap", 1}, // 3238
- {wxStyledTextCtrl_LineEndWrapExtend, "wxStyledTextCtrl", "lineEndWrapExtend", 1}, // 3239
- {wxStyledTextCtrl_VCHomeWrap, "wxStyledTextCtrl", "vCHomeWrap", 1}, // 3240
- {wxStyledTextCtrl_VCHomeWrapExtend, "wxStyledTextCtrl", "vCHomeWrapExtend", 1}, // 3241
- {wxStyledTextCtrl_LineCopy, "wxStyledTextCtrl", "lineCopy", 1}, // 3242
- {wxStyledTextCtrl_MoveCaretInsideView, "wxStyledTextCtrl", "moveCaretInsideView", 1}, // 3243
- {wxStyledTextCtrl_LineLength, "wxStyledTextCtrl", "lineLength", 2}, // 3244
- {wxStyledTextCtrl_BraceHighlight, "wxStyledTextCtrl", "braceHighlight", 3}, // 3245
- {wxStyledTextCtrl_BraceBadLight, "wxStyledTextCtrl", "braceBadLight", 2}, // 3246
- {wxStyledTextCtrl_BraceMatch, "wxStyledTextCtrl", "braceMatch", 2}, // 3247
- {wxStyledTextCtrl_GetViewEOL, "wxStyledTextCtrl", "getViewEOL", 1}, // 3248
- {wxStyledTextCtrl_SetViewEOL, "wxStyledTextCtrl", "setViewEOL", 2}, // 3249
- {wxStyledTextCtrl_SetModEventMask, "wxStyledTextCtrl", "setModEventMask", 2}, // 3250
- {wxStyledTextCtrl_GetEdgeColumn, "wxStyledTextCtrl", "getEdgeColumn", 1}, // 3251
- {wxStyledTextCtrl_SetEdgeColumn, "wxStyledTextCtrl", "setEdgeColumn", 2}, // 3252
- {wxStyledTextCtrl_SetEdgeMode, "wxStyledTextCtrl", "setEdgeMode", 2}, // 3253
- {wxStyledTextCtrl_GetEdgeMode, "wxStyledTextCtrl", "getEdgeMode", 1}, // 3254
- {wxStyledTextCtrl_GetEdgeColour, "wxStyledTextCtrl", "getEdgeColour", 1}, // 3255
- {wxStyledTextCtrl_SetEdgeColour, "wxStyledTextCtrl", "setEdgeColour", 2}, // 3256
- {wxStyledTextCtrl_SearchAnchor, "wxStyledTextCtrl", "searchAnchor", 1}, // 3257
- {wxStyledTextCtrl_SearchNext, "wxStyledTextCtrl", "searchNext", 3}, // 3258
- {wxStyledTextCtrl_SearchPrev, "wxStyledTextCtrl", "searchPrev", 3}, // 3259
- {wxStyledTextCtrl_LinesOnScreen, "wxStyledTextCtrl", "linesOnScreen", 1}, // 3260
- {wxStyledTextCtrl_UsePopUp, "wxStyledTextCtrl", "usePopUp", 2}, // 3261
- {wxStyledTextCtrl_SelectionIsRectangle, "wxStyledTextCtrl", "selectionIsRectangle", 1}, // 3262
- {wxStyledTextCtrl_SetZoom, "wxStyledTextCtrl", "setZoom", 2}, // 3263
- {wxStyledTextCtrl_GetZoom, "wxStyledTextCtrl", "getZoom", 1}, // 3264
- {wxStyledTextCtrl_GetModEventMask, "wxStyledTextCtrl", "getModEventMask", 1}, // 3265
- {wxStyledTextCtrl_SetSTCFocus, "wxStyledTextCtrl", "setSTCFocus", 2}, // 3266
- {wxStyledTextCtrl_GetSTCFocus, "wxStyledTextCtrl", "getSTCFocus", 1}, // 3267
- {wxStyledTextCtrl_SetStatus, "wxStyledTextCtrl", "setStatus", 2}, // 3268
- {wxStyledTextCtrl_GetStatus, "wxStyledTextCtrl", "getStatus", 1}, // 3269
- {wxStyledTextCtrl_SetMouseDownCaptures, "wxStyledTextCtrl", "setMouseDownCaptures", 2}, // 3270
- {wxStyledTextCtrl_GetMouseDownCaptures, "wxStyledTextCtrl", "getMouseDownCaptures", 1}, // 3271
- {wxStyledTextCtrl_SetSTCCursor, "wxStyledTextCtrl", "setSTCCursor", 2}, // 3272
- {wxStyledTextCtrl_GetSTCCursor, "wxStyledTextCtrl", "getSTCCursor", 1}, // 3273
- {wxStyledTextCtrl_SetControlCharSymbol, "wxStyledTextCtrl", "setControlCharSymbol", 2}, // 3274
- {wxStyledTextCtrl_GetControlCharSymbol, "wxStyledTextCtrl", "getControlCharSymbol", 1}, // 3275
- {wxStyledTextCtrl_WordPartLeft, "wxStyledTextCtrl", "wordPartLeft", 1}, // 3276
- {wxStyledTextCtrl_WordPartLeftExtend, "wxStyledTextCtrl", "wordPartLeftExtend", 1}, // 3277
- {wxStyledTextCtrl_WordPartRight, "wxStyledTextCtrl", "wordPartRight", 1}, // 3278
- {wxStyledTextCtrl_WordPartRightExtend, "wxStyledTextCtrl", "wordPartRightExtend", 1}, // 3279
- {wxStyledTextCtrl_SetVisiblePolicy, "wxStyledTextCtrl", "setVisiblePolicy", 3}, // 3280
- {wxStyledTextCtrl_DelLineLeft, "wxStyledTextCtrl", "delLineLeft", 1}, // 3281
- {wxStyledTextCtrl_DelLineRight, "wxStyledTextCtrl", "delLineRight", 1}, // 3282
- {wxStyledTextCtrl_GetXOffset, "wxStyledTextCtrl", "getXOffset", 1}, // 3283
- {wxStyledTextCtrl_ChooseCaretX, "wxStyledTextCtrl", "chooseCaretX", 1}, // 3284
- {wxStyledTextCtrl_SetXCaretPolicy, "wxStyledTextCtrl", "setXCaretPolicy", 3}, // 3285
- {wxStyledTextCtrl_SetYCaretPolicy, "wxStyledTextCtrl", "setYCaretPolicy", 3}, // 3286
- {wxStyledTextCtrl_GetPrintWrapMode, "wxStyledTextCtrl", "getPrintWrapMode", 1}, // 3287
- {wxStyledTextCtrl_SetHotspotActiveForeground, "wxStyledTextCtrl", "setHotspotActiveForeground", 3}, // 3288
- {wxStyledTextCtrl_SetHotspotActiveBackground, "wxStyledTextCtrl", "setHotspotActiveBackground", 3}, // 3289
- {wxStyledTextCtrl_SetHotspotActiveUnderline, "wxStyledTextCtrl", "setHotspotActiveUnderline", 2}, // 3290
- {wxStyledTextCtrl_SetHotspotSingleLine, "wxStyledTextCtrl", "setHotspotSingleLine", 2}, // 3291
- {wxStyledTextCtrl_ParaDownExtend, "wxStyledTextCtrl", "paraDownExtend", 1}, // 3292
- {wxStyledTextCtrl_ParaUp, "wxStyledTextCtrl", "paraUp", 1}, // 3293
- {wxStyledTextCtrl_ParaUpExtend, "wxStyledTextCtrl", "paraUpExtend", 1}, // 3294
- {wxStyledTextCtrl_PositionBefore, "wxStyledTextCtrl", "positionBefore", 2}, // 3295
- {wxStyledTextCtrl_PositionAfter, "wxStyledTextCtrl", "positionAfter", 2}, // 3296
- {wxStyledTextCtrl_CopyRange, "wxStyledTextCtrl", "copyRange", 3}, // 3297
- {wxStyledTextCtrl_CopyText, "wxStyledTextCtrl", "copyText", 3}, // 3298
- {wxStyledTextCtrl_SetSelectionMode, "wxStyledTextCtrl", "setSelectionMode", 2}, // 3299
- {wxStyledTextCtrl_GetSelectionMode, "wxStyledTextCtrl", "getSelectionMode", 1}, // 3300
- {wxStyledTextCtrl_LineDownRectExtend, "wxStyledTextCtrl", "lineDownRectExtend", 1}, // 3301
- {wxStyledTextCtrl_LineUpRectExtend, "wxStyledTextCtrl", "lineUpRectExtend", 1}, // 3302
- {wxStyledTextCtrl_CharLeftRectExtend, "wxStyledTextCtrl", "charLeftRectExtend", 1}, // 3303
- {wxStyledTextCtrl_CharRightRectExtend, "wxStyledTextCtrl", "charRightRectExtend", 1}, // 3304
- {wxStyledTextCtrl_HomeRectExtend, "wxStyledTextCtrl", "homeRectExtend", 1}, // 3305
- {wxStyledTextCtrl_VCHomeRectExtend, "wxStyledTextCtrl", "vCHomeRectExtend", 1}, // 3306
- {wxStyledTextCtrl_LineEndRectExtend, "wxStyledTextCtrl", "lineEndRectExtend", 1}, // 3307
- {wxStyledTextCtrl_PageUpRectExtend, "wxStyledTextCtrl", "pageUpRectExtend", 1}, // 3308
- {wxStyledTextCtrl_PageDownRectExtend, "wxStyledTextCtrl", "pageDownRectExtend", 1}, // 3309
- {wxStyledTextCtrl_StutteredPageUp, "wxStyledTextCtrl", "stutteredPageUp", 1}, // 3310
- {wxStyledTextCtrl_StutteredPageUpExtend, "wxStyledTextCtrl", "stutteredPageUpExtend", 1}, // 3311
- {wxStyledTextCtrl_StutteredPageDown, "wxStyledTextCtrl", "stutteredPageDown", 1}, // 3312
- {wxStyledTextCtrl_StutteredPageDownExtend, "wxStyledTextCtrl", "stutteredPageDownExtend", 1}, // 3313
- {wxStyledTextCtrl_WordLeftEnd, "wxStyledTextCtrl", "wordLeftEnd", 1}, // 3314
- {wxStyledTextCtrl_WordLeftEndExtend, "wxStyledTextCtrl", "wordLeftEndExtend", 1}, // 3315
- {wxStyledTextCtrl_WordRightEnd, "wxStyledTextCtrl", "wordRightEnd", 1}, // 3316
- {wxStyledTextCtrl_WordRightEndExtend, "wxStyledTextCtrl", "wordRightEndExtend", 1}, // 3317
- {wxStyledTextCtrl_SetWhitespaceChars, "wxStyledTextCtrl", "setWhitespaceChars", 2}, // 3318
- {wxStyledTextCtrl_SetCharsDefault, "wxStyledTextCtrl", "setCharsDefault", 1}, // 3319
- {wxStyledTextCtrl_AutoCompGetCurrent, "wxStyledTextCtrl", "autoCompGetCurrent", 1}, // 3320
- {wxStyledTextCtrl_Allocate, "wxStyledTextCtrl", "allocate", 2}, // 3321
- {wxStyledTextCtrl_FindColumn, "wxStyledTextCtrl", "findColumn", 3}, // 3322
- {wxStyledTextCtrl_GetCaretSticky, "wxStyledTextCtrl", "getCaretSticky", 1}, // 3323
- {wxStyledTextCtrl_SetCaretSticky, "wxStyledTextCtrl", "setCaretSticky", 2}, // 3324
- {wxStyledTextCtrl_ToggleCaretSticky, "wxStyledTextCtrl", "toggleCaretSticky", 1}, // 3325
- {wxStyledTextCtrl_SetPasteConvertEndings, "wxStyledTextCtrl", "setPasteConvertEndings", 2}, // 3326
- {wxStyledTextCtrl_GetPasteConvertEndings, "wxStyledTextCtrl", "getPasteConvertEndings", 1}, // 3327
- {wxStyledTextCtrl_SelectionDuplicate, "wxStyledTextCtrl", "selectionDuplicate", 1}, // 3328
- {wxStyledTextCtrl_SetCaretLineBackAlpha, "wxStyledTextCtrl", "setCaretLineBackAlpha", 2}, // 3329
- {wxStyledTextCtrl_GetCaretLineBackAlpha, "wxStyledTextCtrl", "getCaretLineBackAlpha", 1}, // 3330
- {wxStyledTextCtrl_StartRecord, "wxStyledTextCtrl", "startRecord", 1}, // 3331
- {wxStyledTextCtrl_StopRecord, "wxStyledTextCtrl", "stopRecord", 1}, // 3332
- {wxStyledTextCtrl_SetLexer, "wxStyledTextCtrl", "setLexer", 2}, // 3333
- {wxStyledTextCtrl_GetLexer, "wxStyledTextCtrl", "getLexer", 1}, // 3334
- {wxStyledTextCtrl_Colourise, "wxStyledTextCtrl", "colourise", 3}, // 3335
- {wxStyledTextCtrl_SetProperty, "wxStyledTextCtrl", "setProperty", 3}, // 3336
- {wxStyledTextCtrl_SetKeyWords, "wxStyledTextCtrl", "setKeyWords", 3}, // 3337
- {wxStyledTextCtrl_SetLexerLanguage, "wxStyledTextCtrl", "setLexerLanguage", 2}, // 3338
- {wxStyledTextCtrl_GetProperty, "wxStyledTextCtrl", "getProperty", 2}, // 3339
- {wxStyledTextCtrl_GetStyleBitsNeeded, "wxStyledTextCtrl", "getStyleBitsNeeded", 1}, // 3340
- {wxStyledTextCtrl_GetCurrentLine, "wxStyledTextCtrl", "getCurrentLine", 1}, // 3341
- {wxStyledTextCtrl_StyleSetSpec, "wxStyledTextCtrl", "styleSetSpec", 3}, // 3342
- {wxStyledTextCtrl_StyleSetFont, "wxStyledTextCtrl", "styleSetFont", 3}, // 3343
- {wxStyledTextCtrl_StyleSetFontAttr, "wxStyledTextCtrl", "styleSetFontAttr", 8}, // 3344
- {wxStyledTextCtrl_StyleSetCharacterSet, "wxStyledTextCtrl", "styleSetCharacterSet", 3}, // 3345
- {wxStyledTextCtrl_StyleSetFontEncoding, "wxStyledTextCtrl", "styleSetFontEncoding", 3}, // 3346
- {wxStyledTextCtrl_CmdKeyExecute, "wxStyledTextCtrl", "cmdKeyExecute", 2}, // 3347
- {wxStyledTextCtrl_SetMargins, "wxStyledTextCtrl", "setMargins", 3}, // 3348
- {wxStyledTextCtrl_GetSelection, "wxStyledTextCtrl", "getSelection", 1}, // 3349
- {wxStyledTextCtrl_PointFromPosition, "wxStyledTextCtrl", "pointFromPosition", 2}, // 3350
- {wxStyledTextCtrl_ScrollToLine, "wxStyledTextCtrl", "scrollToLine", 2}, // 3351
- {wxStyledTextCtrl_ScrollToColumn, "wxStyledTextCtrl", "scrollToColumn", 2}, // 3352
- {wxStyledTextCtrl_SetVScrollBar, "wxStyledTextCtrl", "setVScrollBar", 2}, // 3353
- {wxStyledTextCtrl_SetHScrollBar, "wxStyledTextCtrl", "setHScrollBar", 2}, // 3354
- {wxStyledTextCtrl_GetLastKeydownProcessed, "wxStyledTextCtrl", "getLastKeydownProcessed", 1}, // 3355
- {wxStyledTextCtrl_SetLastKeydownProcessed, "wxStyledTextCtrl", "setLastKeydownProcessed", 2}, // 3356
- {wxStyledTextCtrl_SaveFile, "wxStyledTextCtrl", "saveFile", 2}, // 3357
- {wxStyledTextCtrl_LoadFile, "wxStyledTextCtrl", "loadFile", 2}, // 3358
- {wxStyledTextCtrl_DoDragOver, "wxStyledTextCtrl", "doDragOver", 4}, // 3359
- {wxStyledTextCtrl_DoDropText, "wxStyledTextCtrl", "doDropText", 4}, // 3360
- {wxStyledTextCtrl_GetUseAntiAliasing, "wxStyledTextCtrl", "getUseAntiAliasing", 1}, // 3361
- {wxStyledTextCtrl_AddTextRaw, "wxStyledTextCtrl", "addTextRaw", 3}, // 3362
- {wxStyledTextCtrl_InsertTextRaw, "wxStyledTextCtrl", "insertTextRaw", 3}, // 3363
- {wxStyledTextCtrl_GetCurLineRaw, "wxStyledTextCtrl", "getCurLineRaw", 1}, // 3364
- {wxStyledTextCtrl_GetLineRaw, "wxStyledTextCtrl", "getLineRaw", 2}, // 3365
- {wxStyledTextCtrl_GetSelectedTextRaw, "wxStyledTextCtrl", "getSelectedTextRaw", 1}, // 3366
- {wxStyledTextCtrl_GetTextRangeRaw, "wxStyledTextCtrl", "getTextRangeRaw", 3}, // 3367
- {wxStyledTextCtrl_SetTextRaw, "wxStyledTextCtrl", "setTextRaw", 2}, // 3368
- {wxStyledTextCtrl_GetTextRaw, "wxStyledTextCtrl", "getTextRaw", 1}, // 3369
- {wxStyledTextCtrl_AppendTextRaw, "wxStyledTextCtrl", "appendTextRaw", 3}, // 3370
- {wxArtProvider_GetBitmap, "wxArtProvider", "getBitmap", 2}, // 3371
- {wxArtProvider_GetIcon, "wxArtProvider", "getIcon", 2}, // 3372
- {wxTreeEvent_GetKeyCode, "wxTreeEvent", "getKeyCode", 1}, // 3373
- {wxTreeEvent_GetItem, "wxTreeEvent", "getItem", 1}, // 3374
- {wxTreeEvent_GetKeyEvent, "wxTreeEvent", "getKeyEvent", 1}, // 3375
- {wxTreeEvent_GetLabel, "wxTreeEvent", "getLabel", 1}, // 3376
- {wxTreeEvent_GetOldItem, "wxTreeEvent", "getOldItem", 1}, // 3377
- {wxTreeEvent_GetPoint, "wxTreeEvent", "getPoint", 1}, // 3378
- {wxTreeEvent_IsEditCancelled, "wxTreeEvent", "isEditCancelled", 1}, // 3379
- {wxTreeEvent_SetToolTip, "wxTreeEvent", "setToolTip", 2}, // 3380
- {wxBookCtrlEvent_GetOldSelection, "wxBookCtrlEvent", "getOldSelection", 1}, // 3381
- {wxBookCtrlEvent_GetSelection, "wxBookCtrlEvent", "getSelection", 1}, // 3382
- {wxBookCtrlEvent_SetOldSelection, "wxBookCtrlEvent", "setOldSelection", 2}, // 3383
- {wxBookCtrlEvent_SetSelection, "wxBookCtrlEvent", "setSelection", 2}, // 3384
- {wxFileDataObject_new, "wxFileDataObject", "new", 0}, // 3385
- {wxFileDataObject_AddFile, "wxFileDataObject", "addFile", 2}, // 3386
- {wxFileDataObject_GetFilenames, "wxFileDataObject", "getFilenames", 1}, // 3387
- {wxFileDataObject_destroy, "wxFileDataObject", "'Destroy'", 1}, // 3388
- {wxTextDataObject_new, "wxTextDataObject", "new", 1}, // 3389
- {wxTextDataObject_GetTextLength, "wxTextDataObject", "getTextLength", 1}, // 3390
- {wxTextDataObject_GetText, "wxTextDataObject", "getText", 1}, // 3391
- {wxTextDataObject_SetText, "wxTextDataObject", "setText", 2}, // 3392
- {wxTextDataObject_destroy, "wxTextDataObject", "'Destroy'", 1}, // 3393
- {wxBitmapDataObject_new_1_1, "wxBitmapDataObject", "new", 1}, // 3394
- {wxBitmapDataObject_new_1_0, "wxBitmapDataObject", "new", 1}, // 3395
- {wxBitmapDataObject_GetBitmap, "wxBitmapDataObject", "getBitmap", 1}, // 3396
- {wxBitmapDataObject_SetBitmap, "wxBitmapDataObject", "setBitmap", 2}, // 3397
- {wxBitmapDataObject_destroy, "wxBitmapDataObject", "'Destroy'", 1}, // 3398
- {wxClipboard_new, "wxClipboard", "new", 0}, // 3399
- {NULL, "wxClipboard", "destroy", 1}, // 3400 obj destructor wxClipboard_destruct
- {wxClipboard_AddData, "wxClipboard", "addData", 2}, // 3401
- {wxClipboard_Clear, "wxClipboard", "clear", 1}, // 3402
- {wxClipboard_Close, "wxClipboard", "close", 1}, // 3403
- {wxClipboard_Flush, "wxClipboard", "flush", 1}, // 3404
- {wxClipboard_GetData, "wxClipboard", "getData", 2}, // 3405
- {wxClipboard_IsOpened, "wxClipboard", "isOpened", 1}, // 3406
- {wxClipboard_Open, "wxClipboard", "open", 1}, // 3407
- {wxClipboard_SetData, "wxClipboard", "setData", 2}, // 3408
- {wxClipboard_UsePrimarySelection, "wxClipboard", "usePrimarySelection", 2}, // 3409
- {wxClipboard_IsSupported, "wxClipboard", "isSupported", 2}, // 3410
- {wxClipboard_Get, "wxClipboard", "get", 0}, // 3411
- {wxSpinEvent_GetPosition, "wxSpinEvent", "getPosition", 1}, // 3412
- {wxSpinEvent_SetPosition, "wxSpinEvent", "setPosition", 2}, // 3413
- {wxSplitterWindow_new_0, "wxSplitterWindow", "new", 0}, // 3414
- {wxSplitterWindow_new_2, "wxSplitterWindow", "new", 2}, // 3415
- {NULL, "wxSplitterWindow", "destroy", 1}, // 3416 obj destructor wxSplitterWindow_destruct
- {wxSplitterWindow_Create, "wxSplitterWindow", "create", 3}, // 3417
- {wxSplitterWindow_GetMinimumPaneSize, "wxSplitterWindow", "getMinimumPaneSize", 1}, // 3418
- {wxSplitterWindow_GetSashGravity, "wxSplitterWindow", "getSashGravity", 1}, // 3419
- {wxSplitterWindow_GetSashPosition, "wxSplitterWindow", "getSashPosition", 1}, // 3420
- {wxSplitterWindow_GetSplitMode, "wxSplitterWindow", "getSplitMode", 1}, // 3421
- {wxSplitterWindow_GetWindow1, "wxSplitterWindow", "getWindow1", 1}, // 3422
- {wxSplitterWindow_GetWindow2, "wxSplitterWindow", "getWindow2", 1}, // 3423
- {wxSplitterWindow_Initialize, "wxSplitterWindow", "initialize", 2}, // 3424
- {wxSplitterWindow_IsSplit, "wxSplitterWindow", "isSplit", 1}, // 3425
- {wxSplitterWindow_ReplaceWindow, "wxSplitterWindow", "replaceWindow", 3}, // 3426
- {wxSplitterWindow_SetSashGravity, "wxSplitterWindow", "setSashGravity", 2}, // 3427
- {wxSplitterWindow_SetSashPosition, "wxSplitterWindow", "setSashPosition", 3}, // 3428
- {wxSplitterWindow_SetMinimumPaneSize, "wxSplitterWindow", "setMinimumPaneSize", 2}, // 3429
- {wxSplitterWindow_SetSplitMode, "wxSplitterWindow", "setSplitMode", 2}, // 3430
- {wxSplitterWindow_SplitHorizontally, "wxSplitterWindow", "splitHorizontally", 4}, // 3431
- {wxSplitterWindow_SplitVertically, "wxSplitterWindow", "splitVertically", 4}, // 3432
- {wxSplitterWindow_Unsplit, "wxSplitterWindow", "unsplit", 2}, // 3433
- {wxSplitterWindow_UpdateSize, "wxSplitterWindow", "updateSize", 1}, // 3434
- {wxSplitterEvent_GetSashPosition, "wxSplitterEvent", "getSashPosition", 1}, // 3435
- {wxSplitterEvent_GetX, "wxSplitterEvent", "getX", 1}, // 3436
- {wxSplitterEvent_GetY, "wxSplitterEvent", "getY", 1}, // 3437
- {wxSplitterEvent_GetWindowBeingRemoved, "wxSplitterEvent", "getWindowBeingRemoved", 1}, // 3438
- {wxSplitterEvent_SetSashPosition, "wxSplitterEvent", "setSashPosition", 2}, // 3439
- {wxHtmlWindow_new_0, "wxHtmlWindow", "new", 0}, // 3440
- {wxHtmlWindow_new_2, "wxHtmlWindow", "new", 2}, // 3441
- {wxHtmlWindow_AppendToPage, "wxHtmlWindow", "appendToPage", 2}, // 3442
- {wxHtmlWindow_GetOpenedAnchor, "wxHtmlWindow", "getOpenedAnchor", 1}, // 3443
- {wxHtmlWindow_GetOpenedPage, "wxHtmlWindow", "getOpenedPage", 1}, // 3444
- {wxHtmlWindow_GetOpenedPageTitle, "wxHtmlWindow", "getOpenedPageTitle", 1}, // 3445
- {wxHtmlWindow_GetRelatedFrame, "wxHtmlWindow", "getRelatedFrame", 1}, // 3446
- {wxHtmlWindow_HistoryBack, "wxHtmlWindow", "historyBack", 1}, // 3447
- {wxHtmlWindow_HistoryCanBack, "wxHtmlWindow", "historyCanBack", 1}, // 3448
- {wxHtmlWindow_HistoryCanForward, "wxHtmlWindow", "historyCanForward", 1}, // 3449
- {wxHtmlWindow_HistoryClear, "wxHtmlWindow", "historyClear", 1}, // 3450
- {wxHtmlWindow_HistoryForward, "wxHtmlWindow", "historyForward", 1}, // 3451
- {wxHtmlWindow_LoadFile, "wxHtmlWindow", "loadFile", 2}, // 3452
- {wxHtmlWindow_LoadPage, "wxHtmlWindow", "loadPage", 2}, // 3453
- {wxHtmlWindow_SelectAll, "wxHtmlWindow", "selectAll", 1}, // 3454
- {wxHtmlWindow_SelectionToText, "wxHtmlWindow", "selectionToText", 1}, // 3455
- {wxHtmlWindow_SelectLine, "wxHtmlWindow", "selectLine", 2}, // 3456
- {wxHtmlWindow_SelectWord, "wxHtmlWindow", "selectWord", 2}, // 3457
- {wxHtmlWindow_SetBorders, "wxHtmlWindow", "setBorders", 2}, // 3458
- {wxHtmlWindow_SetFonts, "wxHtmlWindow", "setFonts", 4}, // 3459
- {wxHtmlWindow_SetPage, "wxHtmlWindow", "setPage", 2}, // 3460
- {wxHtmlWindow_SetRelatedFrame, "wxHtmlWindow", "setRelatedFrame", 3}, // 3461
- {wxHtmlWindow_SetRelatedStatusBar_1, "wxHtmlWindow", "setRelatedStatusBar", 2}, // 3462
- {wxHtmlWindow_SetRelatedStatusBar_2, "wxHtmlWindow", "setRelatedStatusBar", 3}, // 3463
- {wxHtmlWindow_ToText, "wxHtmlWindow", "toText", 1}, // 3464
- {NULL, "wxHtmlWindow", "'Destroy'", 1}, // 3465 obj destructor wxHtmlWindow_destroy
- {wxHtmlLinkEvent_GetLinkInfo, "wxHtmlLinkEvent", "getLinkInfo", 1}, // 3466
- {wxSystemSettings_GetColour, "wxSystemSettings", "getColour", 1}, // 3467
- {wxSystemSettings_GetFont, "wxSystemSettings", "getFont", 1}, // 3468
- {wxSystemSettings_GetMetric, "wxSystemSettings", "getMetric", 2}, // 3469
- {wxSystemSettings_GetScreenType, "wxSystemSettings", "getScreenType", 0}, // 3470
- {wxSystemOptions_GetOption, "wxSystemOptions", "getOption", 1}, // 3471
- {wxSystemOptions_GetOptionInt, "wxSystemOptions", "getOptionInt", 1}, // 3472
- {wxSystemOptions_HasOption, "wxSystemOptions", "hasOption", 1}, // 3473
- {wxSystemOptions_IsFalse, "wxSystemOptions", "isFalse", 1}, // 3474
- {wxSystemOptions_SetOption_2_1, "wxSystemOptions", "setOption", 2}, // 3475
- {wxSystemOptions_SetOption_2_0, "wxSystemOptions", "setOption", 2}, // 3476
- {wxAuiNotebookEvent_SetSelection, "wxAuiNotebookEvent", "setSelection", 2}, // 3477
- {wxAuiNotebookEvent_GetSelection, "wxAuiNotebookEvent", "getSelection", 1}, // 3478
- {wxAuiNotebookEvent_SetOldSelection, "wxAuiNotebookEvent", "setOldSelection", 2}, // 3479
- {wxAuiNotebookEvent_GetOldSelection, "wxAuiNotebookEvent", "getOldSelection", 1}, // 3480
- {wxAuiNotebookEvent_SetDragSource, "wxAuiNotebookEvent", "setDragSource", 2}, // 3481
- {wxAuiNotebookEvent_GetDragSource, "wxAuiNotebookEvent", "getDragSource", 1}, // 3482
- {wxAuiManagerEvent_SetManager, "wxAuiManagerEvent", "setManager", 2}, // 3483
- {wxAuiManagerEvent_GetManager, "wxAuiManagerEvent", "getManager", 1}, // 3484
- {wxAuiManagerEvent_SetPane, "wxAuiManagerEvent", "setPane", 2}, // 3485
- {wxAuiManagerEvent_GetPane, "wxAuiManagerEvent", "getPane", 1}, // 3486
- {wxAuiManagerEvent_SetButton, "wxAuiManagerEvent", "setButton", 2}, // 3487
- {wxAuiManagerEvent_GetButton, "wxAuiManagerEvent", "getButton", 1}, // 3488
- {wxAuiManagerEvent_SetDC, "wxAuiManagerEvent", "setDC", 2}, // 3489
- {wxAuiManagerEvent_GetDC, "wxAuiManagerEvent", "getDC", 1}, // 3490
- {wxAuiManagerEvent_Veto, "wxAuiManagerEvent", "veto", 2}, // 3491
- {wxAuiManagerEvent_GetVeto, "wxAuiManagerEvent", "getVeto", 1}, // 3492
- {wxAuiManagerEvent_SetCanVeto, "wxAuiManagerEvent", "setCanVeto", 2}, // 3493
- {wxAuiManagerEvent_CanVeto, "wxAuiManagerEvent", "canVeto", 1}, // 3494
- {wxLogNull_new, "wxLogNull", "new", 0}, // 3495
- {wxLogNull_destruct, "wxLogNull", "destroy", 1}, // 3496
- {wxTaskBarIcon_new, "wxTaskBarIcon", "new", 1}, // 3497
- {NULL, "wxTaskBarIcon", "destroy", 1}, // 3498 obj destructor wxTaskBarIcon_destruct
- {wxTaskBarIcon_PopupMenu, "wxTaskBarIcon", "popupMenu", 2}, // 3499
- {wxTaskBarIcon_RemoveIcon, "wxTaskBarIcon", "removeIcon", 1}, // 3500
- {wxTaskBarIcon_SetIcon, "wxTaskBarIcon", "setIcon", 3}, // 3501
- {wxLocale_new_0, "wxLocale", "new", 0}, // 3502
- {wxLocale_new_2_0, "wxLocale", "new", 2}, // 3503
- {wxLocale_new_2_1, "wxLocale", "new", 2}, // 3504
- {wxLocale_destruct, "wxLocale", "destroy", 1}, // 3505
- {wxLocale_Init_1, "wxLocale", "init", 2}, // 3506
- {wxLocale_Init_2, "wxLocale", "init", 3}, // 3507
- {wxLocale_AddCatalog_1, "wxLocale", "addCatalog", 2}, // 3508
- {wxLocale_AddCatalog_2, "wxLocale", "addCatalog", 3}, // 3509
- {wxLocale_AddCatalog_3, "wxLocale", "addCatalog", 4}, // 3510
- {wxLocale_AddCatalogLookupPathPrefix, "wxLocale", "addCatalogLookupPathPrefix", 1}, // 3511
- {wxLocale_GetCanonicalName, "wxLocale", "getCanonicalName", 1}, // 3512
- {wxLocale_GetLanguage, "wxLocale", "getLanguage", 1}, // 3513
- {wxLocale_GetLanguageName, "wxLocale", "getLanguageName", 1}, // 3514
- {wxLocale_GetLocale, "wxLocale", "getLocale", 1}, // 3515
- {wxLocale_GetName, "wxLocale", "getName", 1}, // 3516
- {wxLocale_GetString_2, "wxLocale", "getString", 3}, // 3517
- {wxLocale_GetString_4, "wxLocale", "getString", 5}, // 3518
- {wxLocale_GetHeaderValue, "wxLocale", "getHeaderValue", 3}, // 3519
- {wxLocale_GetSysName, "wxLocale", "getSysName", 1}, // 3520
- {wxLocale_GetSystemEncoding, "wxLocale", "getSystemEncoding", 0}, // 3521
- {wxLocale_GetSystemEncodingName, "wxLocale", "getSystemEncodingName", 0}, // 3522
- {wxLocale_GetSystemLanguage, "wxLocale", "getSystemLanguage", 0}, // 3523
- {wxLocale_IsLoaded, "wxLocale", "isLoaded", 2}, // 3524
- {wxLocale_IsOk, "wxLocale", "isOk", 1}, // 3525
- {wxActivateEvent_GetActive, "wxActivateEvent", "getActive", 1}, // 3526
+ {wxMDIParentFrame_new_0, "wxMDIParentFrame", "new", 0}, // 2651
+ {wxMDIParentFrame_new_4, "wxMDIParentFrame", "new", 4}, // 2652
+ {NULL, "wxMDIParentFrame", "destroy", 1}, // 2653 obj destructor wxMDIParentFrame_destruct
+ {wxMDIParentFrame_ActivateNext, "wxMDIParentFrame", "activateNext", 1}, // 2654
+ {wxMDIParentFrame_ActivatePrevious, "wxMDIParentFrame", "activatePrevious", 1}, // 2655
+ {wxMDIParentFrame_ArrangeIcons, "wxMDIParentFrame", "arrangeIcons", 1}, // 2656
+ {wxMDIParentFrame_Cascade, "wxMDIParentFrame", "cascade", 1}, // 2657
+ {wxMDIParentFrame_Create, "wxMDIParentFrame", "create", 5}, // 2658
+ {wxMDIParentFrame_GetActiveChild, "wxMDIParentFrame", "getActiveChild", 1}, // 2659
+ {wxMDIParentFrame_GetClientWindow, "wxMDIParentFrame", "getClientWindow", 1}, // 2660
+ {wxMDIParentFrame_Tile, "wxMDIParentFrame", "tile", 2}, // 2661
+ {wxMDIChildFrame_new_0, "wxMDIChildFrame", "new", 0}, // 2662
+ {wxMDIChildFrame_new_4, "wxMDIChildFrame", "new", 4}, // 2663
+ {NULL, "wxMDIChildFrame", "destroy", 1}, // 2664 obj destructor wxMDIChildFrame_destruct
+ {wxMDIChildFrame_Activate, "wxMDIChildFrame", "activate", 1}, // 2665
+ {wxMDIChildFrame_Create, "wxMDIChildFrame", "create", 5}, // 2666
+ {wxMDIChildFrame_Maximize, "wxMDIChildFrame", "maximize", 2}, // 2667
+ {wxMDIChildFrame_Restore, "wxMDIChildFrame", "restore", 1}, // 2668
+ {wxMDIClientWindow_new, "wxMDIClientWindow", "new", 0}, // 2669
+ {wxMDIClientWindow_CreateClient, "wxMDIClientWindow", "createClient", 3}, // 2670
+ {NULL, "wxMDIClientWindow", "'Destroy'", 1}, // 2671 obj destructor wxMDIClientWindow_destroy
+ {wxLayoutAlgorithm_new, "wxLayoutAlgorithm", "new", 0}, // 2672
+ {NULL, "wxLayoutAlgorithm", "destroy", 1}, // 2673 obj destructor wxLayoutAlgorithm_destruct
+ {wxLayoutAlgorithm_LayoutFrame, "wxLayoutAlgorithm", "layoutFrame", 3}, // 2674
+ {wxLayoutAlgorithm_LayoutMDIFrame, "wxLayoutAlgorithm", "layoutMDIFrame", 3}, // 2675
+ {wxLayoutAlgorithm_LayoutWindow, "wxLayoutAlgorithm", "layoutWindow", 3}, // 2676
+ {wxEvent_GetId, "wxEvent", "getId", 1}, // 2677
+ {wxEvent_GetSkipped, "wxEvent", "getSkipped", 1}, // 2678
+ {wxEvent_GetTimestamp, "wxEvent", "getTimestamp", 1}, // 2679
+ {wxEvent_IsCommandEvent, "wxEvent", "isCommandEvent", 1}, // 2680
+ {wxEvent_ResumePropagation, "wxEvent", "resumePropagation", 2}, // 2681
+ {wxEvent_ShouldPropagate, "wxEvent", "shouldPropagate", 1}, // 2682
+ {wxEvent_Skip, "wxEvent", "skip", 2}, // 2683
+ {wxEvent_StopPropagation, "wxEvent", "stopPropagation", 1}, // 2684
+ {wxCommandEvent_getClientData, "wxCommandEvent", "getClientData", 1}, // 2685
+ {wxCommandEvent_GetExtraLong, "wxCommandEvent", "getExtraLong", 1}, // 2686
+ {wxCommandEvent_GetInt, "wxCommandEvent", "getInt", 1}, // 2687
+ {wxCommandEvent_GetSelection, "wxCommandEvent", "getSelection", 1}, // 2688
+ {wxCommandEvent_GetString, "wxCommandEvent", "getString", 1}, // 2689
+ {wxCommandEvent_IsChecked, "wxCommandEvent", "isChecked", 1}, // 2690
+ {wxCommandEvent_IsSelection, "wxCommandEvent", "isSelection", 1}, // 2691
+ {wxCommandEvent_SetInt, "wxCommandEvent", "setInt", 2}, // 2692
+ {wxCommandEvent_SetString, "wxCommandEvent", "setString", 2}, // 2693
+ {wxScrollEvent_GetOrientation, "wxScrollEvent", "getOrientation", 1}, // 2694
+ {wxScrollEvent_GetPosition, "wxScrollEvent", "getPosition", 1}, // 2695
+ {wxScrollWinEvent_GetOrientation, "wxScrollWinEvent", "getOrientation", 1}, // 2696
+ {wxScrollWinEvent_GetPosition, "wxScrollWinEvent", "getPosition", 1}, // 2697
+ {wxMouseEvent_AltDown, "wxMouseEvent", "altDown", 1}, // 2698
+ {wxMouseEvent_Button, "wxMouseEvent", "button", 2}, // 2699
+ {wxMouseEvent_ButtonDClick, "wxMouseEvent", "buttonDClick", 2}, // 2700
+ {wxMouseEvent_ButtonDown, "wxMouseEvent", "buttonDown", 2}, // 2701
+ {wxMouseEvent_ButtonUp, "wxMouseEvent", "buttonUp", 2}, // 2702
+ {wxMouseEvent_CmdDown, "wxMouseEvent", "cmdDown", 1}, // 2703
+ {wxMouseEvent_ControlDown, "wxMouseEvent", "controlDown", 1}, // 2704
+ {wxMouseEvent_Dragging, "wxMouseEvent", "dragging", 1}, // 2705
+ {wxMouseEvent_Entering, "wxMouseEvent", "entering", 1}, // 2706
+ {wxMouseEvent_GetButton, "wxMouseEvent", "getButton", 1}, // 2707
+ {wxMouseEvent_GetPosition, "wxMouseEvent", "getPosition", 1}, // 2708
+ {NULL, "", "", 0}, // 2709
+ {wxMouseEvent_GetLogicalPosition, "wxMouseEvent", "getLogicalPosition", 2}, // 2710
+ {wxMouseEvent_GetLinesPerAction, "wxMouseEvent", "getLinesPerAction", 1}, // 2711
+ {wxMouseEvent_GetWheelRotation, "wxMouseEvent", "getWheelRotation", 1}, // 2712
+ {wxMouseEvent_GetWheelDelta, "wxMouseEvent", "getWheelDelta", 1}, // 2713
+ {wxMouseEvent_GetX, "wxMouseEvent", "getX", 1}, // 2714
+ {wxMouseEvent_GetY, "wxMouseEvent", "getY", 1}, // 2715
+ {wxMouseEvent_IsButton, "wxMouseEvent", "isButton", 1}, // 2716
+ {wxMouseEvent_IsPageScroll, "wxMouseEvent", "isPageScroll", 1}, // 2717
+ {wxMouseEvent_Leaving, "wxMouseEvent", "leaving", 1}, // 2718
+ {wxMouseEvent_LeftDClick, "wxMouseEvent", "leftDClick", 1}, // 2719
+ {wxMouseEvent_LeftDown, "wxMouseEvent", "leftDown", 1}, // 2720
+ {wxMouseEvent_LeftIsDown, "wxMouseEvent", "leftIsDown", 1}, // 2721
+ {wxMouseEvent_LeftUp, "wxMouseEvent", "leftUp", 1}, // 2722
+ {wxMouseEvent_MetaDown, "wxMouseEvent", "metaDown", 1}, // 2723
+ {wxMouseEvent_MiddleDClick, "wxMouseEvent", "middleDClick", 1}, // 2724
+ {wxMouseEvent_MiddleDown, "wxMouseEvent", "middleDown", 1}, // 2725
+ {wxMouseEvent_MiddleIsDown, "wxMouseEvent", "middleIsDown", 1}, // 2726
+ {wxMouseEvent_MiddleUp, "wxMouseEvent", "middleUp", 1}, // 2727
+ {wxMouseEvent_Moving, "wxMouseEvent", "moving", 1}, // 2728
+ {wxMouseEvent_RightDClick, "wxMouseEvent", "rightDClick", 1}, // 2729
+ {wxMouseEvent_RightDown, "wxMouseEvent", "rightDown", 1}, // 2730
+ {wxMouseEvent_RightIsDown, "wxMouseEvent", "rightIsDown", 1}, // 2731
+ {wxMouseEvent_RightUp, "wxMouseEvent", "rightUp", 1}, // 2732
+ {wxMouseEvent_ShiftDown, "wxMouseEvent", "shiftDown", 1}, // 2733
+ {wxMouseEvent_GetWheelAxis, "wxMouseEvent", "getWheelAxis", 1}, // 2734
+ {wxMouseEvent_Aux1DClick, "wxMouseEvent", "aux1DClick", 1}, // 2735
+ {wxMouseEvent_Aux1Down, "wxMouseEvent", "aux1Down", 1}, // 2736
+ {wxMouseEvent_Aux1Up, "wxMouseEvent", "aux1Up", 1}, // 2737
+ {wxMouseEvent_Aux2DClick, "wxMouseEvent", "aux2DClick", 1}, // 2738
+ {wxMouseEvent_Aux2Down, "wxMouseEvent", "aux2Down", 1}, // 2739
+ {wxMouseEvent_Aux2Up, "wxMouseEvent", "aux2Up", 1}, // 2740
+ {wxSetCursorEvent_GetCursor, "wxSetCursorEvent", "getCursor", 1}, // 2741
+ {wxSetCursorEvent_GetX, "wxSetCursorEvent", "getX", 1}, // 2742
+ {wxSetCursorEvent_GetY, "wxSetCursorEvent", "getY", 1}, // 2743
+ {wxSetCursorEvent_HasCursor, "wxSetCursorEvent", "hasCursor", 1}, // 2744
+ {wxSetCursorEvent_SetCursor, "wxSetCursorEvent", "setCursor", 2}, // 2745
+ {wxKeyEvent_AltDown, "wxKeyEvent", "altDown", 1}, // 2746
+ {wxKeyEvent_CmdDown, "wxKeyEvent", "cmdDown", 1}, // 2747
+ {wxKeyEvent_ControlDown, "wxKeyEvent", "controlDown", 1}, // 2748
+ {wxKeyEvent_GetKeyCode, "wxKeyEvent", "getKeyCode", 1}, // 2749
+ {wxKeyEvent_GetModifiers, "wxKeyEvent", "getModifiers", 1}, // 2750
+ {wxKeyEvent_GetPosition, "wxKeyEvent", "getPosition", 1}, // 2751
+ {NULL, "", "", 0}, // 2752
+ {wxKeyEvent_GetRawKeyCode, "wxKeyEvent", "getRawKeyCode", 1}, // 2753
+ {wxKeyEvent_GetRawKeyFlags, "wxKeyEvent", "getRawKeyFlags", 1}, // 2754
+ {wxKeyEvent_GetUnicodeKey, "wxKeyEvent", "getUnicodeKey", 1}, // 2755
+ {wxKeyEvent_GetX, "wxKeyEvent", "getX", 1}, // 2756
+ {wxKeyEvent_GetY, "wxKeyEvent", "getY", 1}, // 2757
+ {wxKeyEvent_HasModifiers, "wxKeyEvent", "hasModifiers", 1}, // 2758
+ {wxKeyEvent_MetaDown, "wxKeyEvent", "metaDown", 1}, // 2759
+ {wxKeyEvent_ShiftDown, "wxKeyEvent", "shiftDown", 1}, // 2760
+ {wxSizeEvent_GetSize, "wxSizeEvent", "getSize", 1}, // 2761
+ {wxSizeEvent_GetRect, "wxSizeEvent", "getRect", 1}, // 2762
+ {wxMoveEvent_GetPosition, "wxMoveEvent", "getPosition", 1}, // 2763
+ {wxMoveEvent_GetRect, "wxMoveEvent", "getRect", 1}, // 2764
+ {wxEraseEvent_GetDC, "wxEraseEvent", "getDC", 1}, // 2765
+ {wxFocusEvent_GetWindow, "wxFocusEvent", "getWindow", 1}, // 2766
+ {wxChildFocusEvent_GetWindow, "wxChildFocusEvent", "getWindow", 1}, // 2767
+ {wxMenuEvent_GetMenu, "wxMenuEvent", "getMenu", 1}, // 2768
+ {wxMenuEvent_GetMenuId, "wxMenuEvent", "getMenuId", 1}, // 2769
+ {wxMenuEvent_IsPopup, "wxMenuEvent", "isPopup", 1}, // 2770
+ {wxCloseEvent_CanVeto, "wxCloseEvent", "canVeto", 1}, // 2771
+ {wxCloseEvent_GetLoggingOff, "wxCloseEvent", "getLoggingOff", 1}, // 2772
+ {wxCloseEvent_SetCanVeto, "wxCloseEvent", "setCanVeto", 2}, // 2773
+ {wxCloseEvent_SetLoggingOff, "wxCloseEvent", "setLoggingOff", 2}, // 2774
+ {wxCloseEvent_Veto, "wxCloseEvent", "veto", 2}, // 2775
+ {wxShowEvent_SetShow, "wxShowEvent", "setShow", 2}, // 2776
+ {wxShowEvent_IsShown, "wxShowEvent", "isShown", 1}, // 2777
+ {wxIconizeEvent_IsIconized, "wxIconizeEvent", "isIconized", 1}, // 2778
+ {wxJoystickEvent_ButtonDown, "wxJoystickEvent", "buttonDown", 2}, // 2779
+ {wxJoystickEvent_ButtonIsDown, "wxJoystickEvent", "buttonIsDown", 2}, // 2780
+ {wxJoystickEvent_ButtonUp, "wxJoystickEvent", "buttonUp", 2}, // 2781
+ {wxJoystickEvent_GetButtonChange, "wxJoystickEvent", "getButtonChange", 1}, // 2782
+ {wxJoystickEvent_GetButtonState, "wxJoystickEvent", "getButtonState", 1}, // 2783
+ {wxJoystickEvent_GetJoystick, "wxJoystickEvent", "getJoystick", 1}, // 2784
+ {wxJoystickEvent_GetPosition, "wxJoystickEvent", "getPosition", 1}, // 2785
+ {wxJoystickEvent_GetZPosition, "wxJoystickEvent", "getZPosition", 1}, // 2786
+ {wxJoystickEvent_IsButton, "wxJoystickEvent", "isButton", 1}, // 2787
+ {wxJoystickEvent_IsMove, "wxJoystickEvent", "isMove", 1}, // 2788
+ {wxJoystickEvent_IsZMove, "wxJoystickEvent", "isZMove", 1}, // 2789
+ {wxUpdateUIEvent_CanUpdate, "wxUpdateUIEvent", "canUpdate", 1}, // 2790
+ {wxUpdateUIEvent_Check, "wxUpdateUIEvent", "check", 2}, // 2791
+ {wxUpdateUIEvent_Enable, "wxUpdateUIEvent", "enable", 2}, // 2792
+ {wxUpdateUIEvent_Show, "wxUpdateUIEvent", "show", 2}, // 2793
+ {wxUpdateUIEvent_GetChecked, "wxUpdateUIEvent", "getChecked", 1}, // 2794
+ {wxUpdateUIEvent_GetEnabled, "wxUpdateUIEvent", "getEnabled", 1}, // 2795
+ {wxUpdateUIEvent_GetShown, "wxUpdateUIEvent", "getShown", 1}, // 2796
+ {wxUpdateUIEvent_GetSetChecked, "wxUpdateUIEvent", "getSetChecked", 1}, // 2797
+ {wxUpdateUIEvent_GetSetEnabled, "wxUpdateUIEvent", "getSetEnabled", 1}, // 2798
+ {wxUpdateUIEvent_GetSetShown, "wxUpdateUIEvent", "getSetShown", 1}, // 2799
+ {wxUpdateUIEvent_GetSetText, "wxUpdateUIEvent", "getSetText", 1}, // 2800
+ {wxUpdateUIEvent_GetText, "wxUpdateUIEvent", "getText", 1}, // 2801
+ {wxUpdateUIEvent_GetMode, "wxUpdateUIEvent", "getMode", 0}, // 2802
+ {wxUpdateUIEvent_GetUpdateInterval, "wxUpdateUIEvent", "getUpdateInterval", 0}, // 2803
+ {wxUpdateUIEvent_ResetUpdateTime, "wxUpdateUIEvent", "resetUpdateTime", 0}, // 2804
+ {wxUpdateUIEvent_SetMode, "wxUpdateUIEvent", "setMode", 1}, // 2805
+ {wxUpdateUIEvent_SetText, "wxUpdateUIEvent", "setText", 2}, // 2806
+ {wxUpdateUIEvent_SetUpdateInterval, "wxUpdateUIEvent", "setUpdateInterval", 1}, // 2807
+ {wxMouseCaptureChangedEvent_GetCapturedWindow, "wxMouseCaptureChangedEvent", "getCapturedWindow", 1}, // 2808
+ {wxPaletteChangedEvent_SetChangedWindow, "wxPaletteChangedEvent", "setChangedWindow", 2}, // 2809
+ {wxPaletteChangedEvent_GetChangedWindow, "wxPaletteChangedEvent", "getChangedWindow", 1}, // 2810
+ {wxQueryNewPaletteEvent_SetPaletteRealized, "wxQueryNewPaletteEvent", "setPaletteRealized", 2}, // 2811
+ {wxQueryNewPaletteEvent_GetPaletteRealized, "wxQueryNewPaletteEvent", "getPaletteRealized", 1}, // 2812
+ {wxNavigationKeyEvent_GetDirection, "wxNavigationKeyEvent", "getDirection", 1}, // 2813
+ {wxNavigationKeyEvent_SetDirection, "wxNavigationKeyEvent", "setDirection", 2}, // 2814
+ {wxNavigationKeyEvent_IsWindowChange, "wxNavigationKeyEvent", "isWindowChange", 1}, // 2815
+ {wxNavigationKeyEvent_SetWindowChange, "wxNavigationKeyEvent", "setWindowChange", 2}, // 2816
+ {wxNavigationKeyEvent_IsFromTab, "wxNavigationKeyEvent", "isFromTab", 1}, // 2817
+ {wxNavigationKeyEvent_SetFromTab, "wxNavigationKeyEvent", "setFromTab", 2}, // 2818
+ {wxNavigationKeyEvent_GetCurrentFocus, "wxNavigationKeyEvent", "getCurrentFocus", 1}, // 2819
+ {wxNavigationKeyEvent_SetCurrentFocus, "wxNavigationKeyEvent", "setCurrentFocus", 2}, // 2820
+ {wxHelpEvent_GetOrigin, "wxHelpEvent", "getOrigin", 1}, // 2821
+ {wxHelpEvent_GetPosition, "wxHelpEvent", "getPosition", 1}, // 2822
+ {wxHelpEvent_SetOrigin, "wxHelpEvent", "setOrigin", 2}, // 2823
+ {wxHelpEvent_SetPosition, "wxHelpEvent", "setPosition", 2}, // 2824
+ {wxContextMenuEvent_GetPosition, "wxContextMenuEvent", "getPosition", 1}, // 2825
+ {wxContextMenuEvent_SetPosition, "wxContextMenuEvent", "setPosition", 2}, // 2826
+ {wxIdleEvent_GetMode, "wxIdleEvent", "getMode", 0}, // 2827
+ {wxIdleEvent_RequestMore, "wxIdleEvent", "requestMore", 2}, // 2828
+ {wxIdleEvent_MoreRequested, "wxIdleEvent", "moreRequested", 1}, // 2829
+ {wxIdleEvent_SetMode, "wxIdleEvent", "setMode", 1}, // 2830
+ {wxGridEvent_AltDown, "wxGridEvent", "altDown", 1}, // 2831
+ {wxGridEvent_ControlDown, "wxGridEvent", "controlDown", 1}, // 2832
+ {wxGridEvent_GetCol, "wxGridEvent", "getCol", 1}, // 2833
+ {wxGridEvent_GetPosition, "wxGridEvent", "getPosition", 1}, // 2834
+ {wxGridEvent_GetRow, "wxGridEvent", "getRow", 1}, // 2835
+ {wxGridEvent_MetaDown, "wxGridEvent", "metaDown", 1}, // 2836
+ {wxGridEvent_Selecting, "wxGridEvent", "selecting", 1}, // 2837
+ {wxGridEvent_ShiftDown, "wxGridEvent", "shiftDown", 1}, // 2838
+ {wxNotifyEvent_Allow, "wxNotifyEvent", "allow", 1}, // 2839
+ {wxNotifyEvent_IsAllowed, "wxNotifyEvent", "isAllowed", 1}, // 2840
+ {wxNotifyEvent_Veto, "wxNotifyEvent", "veto", 1}, // 2841
+ {wxSashEvent_GetEdge, "wxSashEvent", "getEdge", 1}, // 2842
+ {wxSashEvent_GetDragRect, "wxSashEvent", "getDragRect", 1}, // 2843
+ {wxSashEvent_GetDragStatus, "wxSashEvent", "getDragStatus", 1}, // 2844
+ {wxListEvent_GetCacheFrom, "wxListEvent", "getCacheFrom", 1}, // 2845
+ {wxListEvent_GetCacheTo, "wxListEvent", "getCacheTo", 1}, // 2846
+ {wxListEvent_GetKeyCode, "wxListEvent", "getKeyCode", 1}, // 2847
+ {wxListEvent_GetIndex, "wxListEvent", "getIndex", 1}, // 2848
+ {wxListEvent_GetColumn, "wxListEvent", "getColumn", 1}, // 2849
+ {wxListEvent_GetPoint, "wxListEvent", "getPoint", 1}, // 2850
+ {wxListEvent_GetLabel, "wxListEvent", "getLabel", 1}, // 2851
+ {wxListEvent_GetText, "wxListEvent", "getText", 1}, // 2852
+ {wxListEvent_GetImage, "wxListEvent", "getImage", 1}, // 2853
+ {wxListEvent_GetData, "wxListEvent", "getData", 1}, // 2854
+ {wxListEvent_GetMask, "wxListEvent", "getMask", 1}, // 2855
+ {wxListEvent_GetItem, "wxListEvent", "getItem", 1}, // 2856
+ {wxListEvent_IsEditCancelled, "wxListEvent", "isEditCancelled", 1}, // 2857
+ {wxDateEvent_GetDate, "wxDateEvent", "getDate", 1}, // 2858
+ {wxCalendarEvent_GetWeekDay, "wxCalendarEvent", "getWeekDay", 1}, // 2859
+ {wxCalendarEvent_GetDate, "wxCalendarEvent", "getDate", 1}, // 2860
+ {wxFileDirPickerEvent_GetPath, "wxFileDirPickerEvent", "getPath", 1}, // 2861
+ {wxColourPickerEvent_GetColour, "wxColourPickerEvent", "getColour", 1}, // 2862
+ {wxFontPickerEvent_GetFont, "wxFontPickerEvent", "getFont", 1}, // 2863
+ {wxStyledTextEvent_GetPosition, "wxStyledTextEvent", "getPosition", 1}, // 2864
+ {wxStyledTextEvent_GetKey, "wxStyledTextEvent", "getKey", 1}, // 2865
+ {wxStyledTextEvent_GetModifiers, "wxStyledTextEvent", "getModifiers", 1}, // 2866
+ {wxStyledTextEvent_GetModificationType, "wxStyledTextEvent", "getModificationType", 1}, // 2867
+ {wxStyledTextEvent_GetText, "wxStyledTextEvent", "getText", 1}, // 2868
+ {wxStyledTextEvent_GetLength, "wxStyledTextEvent", "getLength", 1}, // 2869
+ {wxStyledTextEvent_GetLinesAdded, "wxStyledTextEvent", "getLinesAdded", 1}, // 2870
+ {wxStyledTextEvent_GetLine, "wxStyledTextEvent", "getLine", 1}, // 2871
+ {wxStyledTextEvent_GetFoldLevelNow, "wxStyledTextEvent", "getFoldLevelNow", 1}, // 2872
+ {wxStyledTextEvent_GetFoldLevelPrev, "wxStyledTextEvent", "getFoldLevelPrev", 1}, // 2873
+ {wxStyledTextEvent_GetMargin, "wxStyledTextEvent", "getMargin", 1}, // 2874
+ {wxStyledTextEvent_GetMessage, "wxStyledTextEvent", "getMessage", 1}, // 2875
+ {wxStyledTextEvent_GetWParam, "wxStyledTextEvent", "getWParam", 1}, // 2876
+ {wxStyledTextEvent_GetLParam, "wxStyledTextEvent", "getLParam", 1}, // 2877
+ {wxStyledTextEvent_GetListType, "wxStyledTextEvent", "getListType", 1}, // 2878
+ {wxStyledTextEvent_GetX, "wxStyledTextEvent", "getX", 1}, // 2879
+ {wxStyledTextEvent_GetY, "wxStyledTextEvent", "getY", 1}, // 2880
+ {wxStyledTextEvent_GetDragText, "wxStyledTextEvent", "getDragText", 1}, // 2881
+ {wxStyledTextEvent_GetDragAllowMove, "wxStyledTextEvent", "getDragAllowMove", 1}, // 2882
+ {wxStyledTextEvent_GetDragResult, "wxStyledTextEvent", "getDragResult", 1}, // 2883
+ {wxStyledTextEvent_GetShift, "wxStyledTextEvent", "getShift", 1}, // 2884
+ {wxStyledTextEvent_GetControl, "wxStyledTextEvent", "getControl", 1}, // 2885
+ {wxStyledTextEvent_GetAlt, "wxStyledTextEvent", "getAlt", 1}, // 2886
+ {utils_wxGetKeyState, "utils", "getKeyState", 1}, // 2887
+ {utils_wxGetMousePosition, "utils", "getMousePosition", 0}, // 2888
+ {utils_wxGetMouseState, "utils", "getMouseState", 0}, // 2889
+ {utils_wxSetDetectableAutoRepeat, "utils", "setDetectableAutoRepeat", 1}, // 2890
+ {utils_wxBell, "utils", "bell", 0}, // 2891
+ {utils_wxFindMenuItemId, "utils", "findMenuItemId", 3}, // 2892
+ {utils_wxFindWindowAtPoint, "utils", "findWindowAtPoint", 1}, // 2893
+ {utils_wxBeginBusyCursor, "utils", "beginBusyCursor", 1}, // 2894
+ {utils_wxEndBusyCursor, "utils", "endBusyCursor", 0}, // 2895
+ {utils_wxIsBusy, "utils", "isBusy", 0}, // 2896
+ {utils_wxShutdown, "utils", "shutdown", 1}, // 2897
+ {utils_wxShell, "utils", "shell", 1}, // 2898
+ {utils_wxLaunchDefaultBrowser, "utils", "launchDefaultBrowser", 2}, // 2899
+ {utils_wxGetEmailAddress, "utils", "getEmailAddress", 0}, // 2900
+ {utils_wxGetUserId, "utils", "getUserId", 0}, // 2901
+ {utils_wxGetHomeDir, "utils", "getHomeDir", 0}, // 2902
+ {utils_wxNewId, "utils", "newId", 0}, // 2903
+ {utils_wxRegisterId, "utils", "registerId", 1}, // 2904
+ {utils_wxGetCurrentId, "utils", "getCurrentId", 0}, // 2905
+ {utils_wxGetOsDescription, "utils", "getOsDescription", 0}, // 2906
+ {utils_wxIsPlatformLittleEndian, "utils", "isPlatformLittleEndian", 0}, // 2907
+ {utils_wxIsPlatform64Bit, "utils", "isPlatform64Bit", 0}, // 2908
+ {gdicmn_wxDisplaySize, "gdicmn", "displaySize", 0}, // 2909
+ {gdicmn_wxSetCursor, "gdicmn", "setCursor", 1}, // 2910
+ {wxPrintout_new, "wxPrintout", "new", 3}, // 2911
+ {NULL, "wxPrintout", "destroy", 1}, // 2912 obj destructor wxPrintout_destruct
+ {wxPrintout_GetDC, "wxPrintout", "getDC", 1}, // 2913
+ {wxPrintout_GetPageSizeMM, "wxPrintout", "getPageSizeMM", 1}, // 2914
+ {wxPrintout_GetPageSizePixels, "wxPrintout", "getPageSizePixels", 1}, // 2915
+ {wxPrintout_GetPaperRectPixels, "wxPrintout", "getPaperRectPixels", 1}, // 2916
+ {wxPrintout_GetPPIPrinter, "wxPrintout", "getPPIPrinter", 1}, // 2917
+ {wxPrintout_GetPPIScreen, "wxPrintout", "getPPIScreen", 1}, // 2918
+ {wxPrintout_GetTitle, "wxPrintout", "getTitle", 1}, // 2919
+ {wxPrintout_IsPreview, "wxPrintout", "isPreview", 1}, // 2920
+ {wxPrintout_FitThisSizeToPaper, "wxPrintout", "fitThisSizeToPaper", 2}, // 2921
+ {wxPrintout_FitThisSizeToPage, "wxPrintout", "fitThisSizeToPage", 2}, // 2922
+ {wxPrintout_FitThisSizeToPageMargins, "wxPrintout", "fitThisSizeToPageMargins", 3}, // 2923
+ {wxPrintout_MapScreenSizeToPaper, "wxPrintout", "mapScreenSizeToPaper", 1}, // 2924
+ {wxPrintout_MapScreenSizeToPage, "wxPrintout", "mapScreenSizeToPage", 1}, // 2925
+ {wxPrintout_MapScreenSizeToPageMargins, "wxPrintout", "mapScreenSizeToPageMargins", 2}, // 2926
+ {wxPrintout_MapScreenSizeToDevice, "wxPrintout", "mapScreenSizeToDevice", 1}, // 2927
+ {wxPrintout_GetLogicalPaperRect, "wxPrintout", "getLogicalPaperRect", 1}, // 2928
+ {wxPrintout_GetLogicalPageRect, "wxPrintout", "getLogicalPageRect", 1}, // 2929
+ {wxPrintout_GetLogicalPageMarginsRect, "wxPrintout", "getLogicalPageMarginsRect", 2}, // 2930
+ {wxPrintout_SetLogicalOrigin, "wxPrintout", "setLogicalOrigin", 3}, // 2931
+ {wxPrintout_OffsetLogicalOrigin, "wxPrintout", "offsetLogicalOrigin", 3}, // 2932
+ {wxStyledTextCtrl_new_2, "wxStyledTextCtrl", "new", 2}, // 2933
+ {wxStyledTextCtrl_new_0, "wxStyledTextCtrl", "new", 0}, // 2934
+ {NULL, "wxStyledTextCtrl", "destroy", 1}, // 2935 obj destructor wxStyledTextCtrl_destruct
+ {wxStyledTextCtrl_Create, "wxStyledTextCtrl", "create", 3}, // 2936
+ {wxStyledTextCtrl_AddText, "wxStyledTextCtrl", "addText", 2}, // 2937
+ {wxStyledTextCtrl_InsertText, "wxStyledTextCtrl", "insertText", 3}, // 2938
+ {wxStyledTextCtrl_ClearAll, "wxStyledTextCtrl", "clearAll", 1}, // 2939
+ {wxStyledTextCtrl_ClearDocumentStyle, "wxStyledTextCtrl", "clearDocumentStyle", 1}, // 2940
+ {wxStyledTextCtrl_GetLength, "wxStyledTextCtrl", "getLength", 1}, // 2941
+ {wxStyledTextCtrl_GetCharAt, "wxStyledTextCtrl", "getCharAt", 2}, // 2942
+ {wxStyledTextCtrl_GetCurrentPos, "wxStyledTextCtrl", "getCurrentPos", 1}, // 2943
+ {wxStyledTextCtrl_GetAnchor, "wxStyledTextCtrl", "getAnchor", 1}, // 2944
+ {wxStyledTextCtrl_GetStyleAt, "wxStyledTextCtrl", "getStyleAt", 2}, // 2945
+ {wxStyledTextCtrl_Redo, "wxStyledTextCtrl", "redo", 1}, // 2946
+ {wxStyledTextCtrl_SetUndoCollection, "wxStyledTextCtrl", "setUndoCollection", 2}, // 2947
+ {wxStyledTextCtrl_SelectAll, "wxStyledTextCtrl", "selectAll", 1}, // 2948
+ {wxStyledTextCtrl_SetSavePoint, "wxStyledTextCtrl", "setSavePoint", 1}, // 2949
+ {wxStyledTextCtrl_CanRedo, "wxStyledTextCtrl", "canRedo", 1}, // 2950
+ {wxStyledTextCtrl_MarkerLineFromHandle, "wxStyledTextCtrl", "markerLineFromHandle", 2}, // 2951
+ {wxStyledTextCtrl_MarkerDeleteHandle, "wxStyledTextCtrl", "markerDeleteHandle", 2}, // 2952
+ {wxStyledTextCtrl_GetUndoCollection, "wxStyledTextCtrl", "getUndoCollection", 1}, // 2953
+ {wxStyledTextCtrl_GetViewWhiteSpace, "wxStyledTextCtrl", "getViewWhiteSpace", 1}, // 2954
+ {wxStyledTextCtrl_SetViewWhiteSpace, "wxStyledTextCtrl", "setViewWhiteSpace", 2}, // 2955
+ {wxStyledTextCtrl_PositionFromPoint, "wxStyledTextCtrl", "positionFromPoint", 2}, // 2956
+ {wxStyledTextCtrl_PositionFromPointClose, "wxStyledTextCtrl", "positionFromPointClose", 3}, // 2957
+ {wxStyledTextCtrl_GotoLine, "wxStyledTextCtrl", "gotoLine", 2}, // 2958
+ {wxStyledTextCtrl_GotoPos, "wxStyledTextCtrl", "gotoPos", 2}, // 2959
+ {wxStyledTextCtrl_SetAnchor, "wxStyledTextCtrl", "setAnchor", 2}, // 2960
+ {wxStyledTextCtrl_GetCurLine, "wxStyledTextCtrl", "getCurLine", 1}, // 2961
+ {wxStyledTextCtrl_GetEndStyled, "wxStyledTextCtrl", "getEndStyled", 1}, // 2962
+ {wxStyledTextCtrl_ConvertEOLs, "wxStyledTextCtrl", "convertEOLs", 2}, // 2963
+ {wxStyledTextCtrl_GetEOLMode, "wxStyledTextCtrl", "getEOLMode", 1}, // 2964
+ {wxStyledTextCtrl_SetEOLMode, "wxStyledTextCtrl", "setEOLMode", 2}, // 2965
+ {wxStyledTextCtrl_StartStyling, "wxStyledTextCtrl", "startStyling", 2}, // 2966
+ {wxStyledTextCtrl_SetStyling, "wxStyledTextCtrl", "setStyling", 3}, // 2967
+ {wxStyledTextCtrl_GetBufferedDraw, "wxStyledTextCtrl", "getBufferedDraw", 1}, // 2968
+ {wxStyledTextCtrl_SetBufferedDraw, "wxStyledTextCtrl", "setBufferedDraw", 2}, // 2969
+ {wxStyledTextCtrl_SetTabWidth, "wxStyledTextCtrl", "setTabWidth", 2}, // 2970
+ {wxStyledTextCtrl_GetTabWidth, "wxStyledTextCtrl", "getTabWidth", 1}, // 2971
+ {wxStyledTextCtrl_SetCodePage, "wxStyledTextCtrl", "setCodePage", 2}, // 2972
+ {wxStyledTextCtrl_MarkerDefine, "wxStyledTextCtrl", "markerDefine", 4}, // 2973
+ {wxStyledTextCtrl_MarkerSetForeground, "wxStyledTextCtrl", "markerSetForeground", 3}, // 2974
+ {wxStyledTextCtrl_MarkerSetBackground, "wxStyledTextCtrl", "markerSetBackground", 3}, // 2975
+ {wxStyledTextCtrl_MarkerAdd, "wxStyledTextCtrl", "markerAdd", 3}, // 2976
+ {wxStyledTextCtrl_MarkerDelete, "wxStyledTextCtrl", "markerDelete", 3}, // 2977
+ {wxStyledTextCtrl_MarkerDeleteAll, "wxStyledTextCtrl", "markerDeleteAll", 2}, // 2978
+ {wxStyledTextCtrl_MarkerGet, "wxStyledTextCtrl", "markerGet", 2}, // 2979
+ {wxStyledTextCtrl_MarkerNext, "wxStyledTextCtrl", "markerNext", 3}, // 2980
+ {wxStyledTextCtrl_MarkerPrevious, "wxStyledTextCtrl", "markerPrevious", 3}, // 2981
+ {wxStyledTextCtrl_MarkerDefineBitmap, "wxStyledTextCtrl", "markerDefineBitmap", 3}, // 2982
+ {wxStyledTextCtrl_MarkerAddSet, "wxStyledTextCtrl", "markerAddSet", 3}, // 2983
+ {wxStyledTextCtrl_MarkerSetAlpha, "wxStyledTextCtrl", "markerSetAlpha", 3}, // 2984
+ {wxStyledTextCtrl_SetMarginType, "wxStyledTextCtrl", "setMarginType", 3}, // 2985
+ {wxStyledTextCtrl_GetMarginType, "wxStyledTextCtrl", "getMarginType", 2}, // 2986
+ {wxStyledTextCtrl_SetMarginWidth, "wxStyledTextCtrl", "setMarginWidth", 3}, // 2987
+ {wxStyledTextCtrl_GetMarginWidth, "wxStyledTextCtrl", "getMarginWidth", 2}, // 2988
+ {wxStyledTextCtrl_SetMarginMask, "wxStyledTextCtrl", "setMarginMask", 3}, // 2989
+ {wxStyledTextCtrl_GetMarginMask, "wxStyledTextCtrl", "getMarginMask", 2}, // 2990
+ {wxStyledTextCtrl_SetMarginSensitive, "wxStyledTextCtrl", "setMarginSensitive", 3}, // 2991
+ {wxStyledTextCtrl_GetMarginSensitive, "wxStyledTextCtrl", "getMarginSensitive", 2}, // 2992
+ {wxStyledTextCtrl_StyleClearAll, "wxStyledTextCtrl", "styleClearAll", 1}, // 2993
+ {wxStyledTextCtrl_StyleSetForeground, "wxStyledTextCtrl", "styleSetForeground", 3}, // 2994
+ {wxStyledTextCtrl_StyleSetBackground, "wxStyledTextCtrl", "styleSetBackground", 3}, // 2995
+ {wxStyledTextCtrl_StyleSetBold, "wxStyledTextCtrl", "styleSetBold", 3}, // 2996
+ {wxStyledTextCtrl_StyleSetItalic, "wxStyledTextCtrl", "styleSetItalic", 3}, // 2997
+ {wxStyledTextCtrl_StyleSetSize, "wxStyledTextCtrl", "styleSetSize", 3}, // 2998
+ {wxStyledTextCtrl_StyleSetFaceName, "wxStyledTextCtrl", "styleSetFaceName", 3}, // 2999
+ {wxStyledTextCtrl_StyleSetEOLFilled, "wxStyledTextCtrl", "styleSetEOLFilled", 3}, // 3000
+ {wxStyledTextCtrl_StyleResetDefault, "wxStyledTextCtrl", "styleResetDefault", 1}, // 3001
+ {wxStyledTextCtrl_StyleSetUnderline, "wxStyledTextCtrl", "styleSetUnderline", 3}, // 3002
+ {wxStyledTextCtrl_StyleSetCase, "wxStyledTextCtrl", "styleSetCase", 3}, // 3003
+ {wxStyledTextCtrl_StyleSetHotSpot, "wxStyledTextCtrl", "styleSetHotSpot", 3}, // 3004
+ {wxStyledTextCtrl_SetSelForeground, "wxStyledTextCtrl", "setSelForeground", 3}, // 3005
+ {wxStyledTextCtrl_SetSelBackground, "wxStyledTextCtrl", "setSelBackground", 3}, // 3006
+ {wxStyledTextCtrl_GetSelAlpha, "wxStyledTextCtrl", "getSelAlpha", 1}, // 3007
+ {wxStyledTextCtrl_SetSelAlpha, "wxStyledTextCtrl", "setSelAlpha", 2}, // 3008
+ {wxStyledTextCtrl_SetCaretForeground, "wxStyledTextCtrl", "setCaretForeground", 2}, // 3009
+ {wxStyledTextCtrl_CmdKeyAssign, "wxStyledTextCtrl", "cmdKeyAssign", 4}, // 3010
+ {wxStyledTextCtrl_CmdKeyClear, "wxStyledTextCtrl", "cmdKeyClear", 3}, // 3011
+ {wxStyledTextCtrl_CmdKeyClearAll, "wxStyledTextCtrl", "cmdKeyClearAll", 1}, // 3012
+ {wxStyledTextCtrl_SetStyleBytes, "wxStyledTextCtrl", "setStyleBytes", 2}, // 3013
+ {wxStyledTextCtrl_StyleSetVisible, "wxStyledTextCtrl", "styleSetVisible", 3}, // 3014
+ {wxStyledTextCtrl_GetCaretPeriod, "wxStyledTextCtrl", "getCaretPeriod", 1}, // 3015
+ {wxStyledTextCtrl_SetCaretPeriod, "wxStyledTextCtrl", "setCaretPeriod", 2}, // 3016
+ {wxStyledTextCtrl_SetWordChars, "wxStyledTextCtrl", "setWordChars", 2}, // 3017
+ {wxStyledTextCtrl_BeginUndoAction, "wxStyledTextCtrl", "beginUndoAction", 1}, // 3018
+ {wxStyledTextCtrl_EndUndoAction, "wxStyledTextCtrl", "endUndoAction", 1}, // 3019
+ {wxStyledTextCtrl_IndicatorSetStyle, "wxStyledTextCtrl", "indicatorSetStyle", 3}, // 3020
+ {wxStyledTextCtrl_IndicatorGetStyle, "wxStyledTextCtrl", "indicatorGetStyle", 2}, // 3021
+ {wxStyledTextCtrl_IndicatorSetForeground, "wxStyledTextCtrl", "indicatorSetForeground", 3}, // 3022
+ {wxStyledTextCtrl_IndicatorGetForeground, "wxStyledTextCtrl", "indicatorGetForeground", 2}, // 3023
+ {wxStyledTextCtrl_SetWhitespaceForeground, "wxStyledTextCtrl", "setWhitespaceForeground", 3}, // 3024
+ {wxStyledTextCtrl_SetWhitespaceBackground, "wxStyledTextCtrl", "setWhitespaceBackground", 3}, // 3025
+ {wxStyledTextCtrl_GetStyleBits, "wxStyledTextCtrl", "getStyleBits", 1}, // 3026
+ {wxStyledTextCtrl_SetLineState, "wxStyledTextCtrl", "setLineState", 3}, // 3027
+ {wxStyledTextCtrl_GetLineState, "wxStyledTextCtrl", "getLineState", 2}, // 3028
+ {wxStyledTextCtrl_GetMaxLineState, "wxStyledTextCtrl", "getMaxLineState", 1}, // 3029
+ {wxStyledTextCtrl_GetCaretLineVisible, "wxStyledTextCtrl", "getCaretLineVisible", 1}, // 3030
+ {wxStyledTextCtrl_SetCaretLineVisible, "wxStyledTextCtrl", "setCaretLineVisible", 2}, // 3031
+ {wxStyledTextCtrl_GetCaretLineBackground, "wxStyledTextCtrl", "getCaretLineBackground", 1}, // 3032
+ {wxStyledTextCtrl_SetCaretLineBackground, "wxStyledTextCtrl", "setCaretLineBackground", 2}, // 3033
+ {wxStyledTextCtrl_AutoCompShow, "wxStyledTextCtrl", "autoCompShow", 3}, // 3034
+ {wxStyledTextCtrl_AutoCompCancel, "wxStyledTextCtrl", "autoCompCancel", 1}, // 3035
+ {wxStyledTextCtrl_AutoCompActive, "wxStyledTextCtrl", "autoCompActive", 1}, // 3036
+ {wxStyledTextCtrl_AutoCompPosStart, "wxStyledTextCtrl", "autoCompPosStart", 1}, // 3037
+ {wxStyledTextCtrl_AutoCompComplete, "wxStyledTextCtrl", "autoCompComplete", 1}, // 3038
+ {wxStyledTextCtrl_AutoCompStops, "wxStyledTextCtrl", "autoCompStops", 2}, // 3039
+ {wxStyledTextCtrl_AutoCompSetSeparator, "wxStyledTextCtrl", "autoCompSetSeparator", 2}, // 3040
+ {wxStyledTextCtrl_AutoCompGetSeparator, "wxStyledTextCtrl", "autoCompGetSeparator", 1}, // 3041
+ {wxStyledTextCtrl_AutoCompSelect, "wxStyledTextCtrl", "autoCompSelect", 2}, // 3042
+ {wxStyledTextCtrl_AutoCompSetCancelAtStart, "wxStyledTextCtrl", "autoCompSetCancelAtStart", 2}, // 3043
+ {wxStyledTextCtrl_AutoCompGetCancelAtStart, "wxStyledTextCtrl", "autoCompGetCancelAtStart", 1}, // 3044
+ {wxStyledTextCtrl_AutoCompSetFillUps, "wxStyledTextCtrl", "autoCompSetFillUps", 2}, // 3045
+ {wxStyledTextCtrl_AutoCompSetChooseSingle, "wxStyledTextCtrl", "autoCompSetChooseSingle", 2}, // 3046
+ {wxStyledTextCtrl_AutoCompGetChooseSingle, "wxStyledTextCtrl", "autoCompGetChooseSingle", 1}, // 3047
+ {wxStyledTextCtrl_AutoCompSetIgnoreCase, "wxStyledTextCtrl", "autoCompSetIgnoreCase", 2}, // 3048
+ {wxStyledTextCtrl_AutoCompGetIgnoreCase, "wxStyledTextCtrl", "autoCompGetIgnoreCase", 1}, // 3049
+ {wxStyledTextCtrl_UserListShow, "wxStyledTextCtrl", "userListShow", 3}, // 3050
+ {wxStyledTextCtrl_AutoCompSetAutoHide, "wxStyledTextCtrl", "autoCompSetAutoHide", 2}, // 3051
+ {wxStyledTextCtrl_AutoCompGetAutoHide, "wxStyledTextCtrl", "autoCompGetAutoHide", 1}, // 3052
+ {wxStyledTextCtrl_AutoCompSetDropRestOfWord, "wxStyledTextCtrl", "autoCompSetDropRestOfWord", 2}, // 3053
+ {wxStyledTextCtrl_AutoCompGetDropRestOfWord, "wxStyledTextCtrl", "autoCompGetDropRestOfWord", 1}, // 3054
+ {wxStyledTextCtrl_RegisterImage, "wxStyledTextCtrl", "registerImage", 3}, // 3055
+ {wxStyledTextCtrl_ClearRegisteredImages, "wxStyledTextCtrl", "clearRegisteredImages", 1}, // 3056
+ {wxStyledTextCtrl_AutoCompGetTypeSeparator, "wxStyledTextCtrl", "autoCompGetTypeSeparator", 1}, // 3057
+ {wxStyledTextCtrl_AutoCompSetTypeSeparator, "wxStyledTextCtrl", "autoCompSetTypeSeparator", 2}, // 3058
+ {wxStyledTextCtrl_AutoCompSetMaxWidth, "wxStyledTextCtrl", "autoCompSetMaxWidth", 2}, // 3059
+ {wxStyledTextCtrl_AutoCompGetMaxWidth, "wxStyledTextCtrl", "autoCompGetMaxWidth", 1}, // 3060
+ {wxStyledTextCtrl_AutoCompSetMaxHeight, "wxStyledTextCtrl", "autoCompSetMaxHeight", 2}, // 3061
+ {wxStyledTextCtrl_AutoCompGetMaxHeight, "wxStyledTextCtrl", "autoCompGetMaxHeight", 1}, // 3062
+ {wxStyledTextCtrl_SetIndent, "wxStyledTextCtrl", "setIndent", 2}, // 3063
+ {wxStyledTextCtrl_GetIndent, "wxStyledTextCtrl", "getIndent", 1}, // 3064
+ {wxStyledTextCtrl_SetUseTabs, "wxStyledTextCtrl", "setUseTabs", 2}, // 3065
+ {wxStyledTextCtrl_GetUseTabs, "wxStyledTextCtrl", "getUseTabs", 1}, // 3066
+ {wxStyledTextCtrl_SetLineIndentation, "wxStyledTextCtrl", "setLineIndentation", 3}, // 3067
+ {wxStyledTextCtrl_GetLineIndentation, "wxStyledTextCtrl", "getLineIndentation", 2}, // 3068
+ {wxStyledTextCtrl_GetLineIndentPosition, "wxStyledTextCtrl", "getLineIndentPosition", 2}, // 3069
+ {wxStyledTextCtrl_GetColumn, "wxStyledTextCtrl", "getColumn", 2}, // 3070
+ {wxStyledTextCtrl_SetUseHorizontalScrollBar, "wxStyledTextCtrl", "setUseHorizontalScrollBar", 2}, // 3071
+ {wxStyledTextCtrl_GetUseHorizontalScrollBar, "wxStyledTextCtrl", "getUseHorizontalScrollBar", 1}, // 3072
+ {wxStyledTextCtrl_SetIndentationGuides, "wxStyledTextCtrl", "setIndentationGuides", 2}, // 3073
+ {wxStyledTextCtrl_GetIndentationGuides, "wxStyledTextCtrl", "getIndentationGuides", 1}, // 3074
+ {wxStyledTextCtrl_SetHighlightGuide, "wxStyledTextCtrl", "setHighlightGuide", 2}, // 3075
+ {wxStyledTextCtrl_GetHighlightGuide, "wxStyledTextCtrl", "getHighlightGuide", 1}, // 3076
+ {wxStyledTextCtrl_GetLineEndPosition, "wxStyledTextCtrl", "getLineEndPosition", 2}, // 3077
+ {wxStyledTextCtrl_GetCodePage, "wxStyledTextCtrl", "getCodePage", 1}, // 3078
+ {wxStyledTextCtrl_GetCaretForeground, "wxStyledTextCtrl", "getCaretForeground", 1}, // 3079
+ {wxStyledTextCtrl_GetReadOnly, "wxStyledTextCtrl", "getReadOnly", 1}, // 3080
+ {wxStyledTextCtrl_SetCurrentPos, "wxStyledTextCtrl", "setCurrentPos", 2}, // 3081
+ {wxStyledTextCtrl_SetSelectionStart, "wxStyledTextCtrl", "setSelectionStart", 2}, // 3082
+ {wxStyledTextCtrl_GetSelectionStart, "wxStyledTextCtrl", "getSelectionStart", 1}, // 3083
+ {wxStyledTextCtrl_SetSelectionEnd, "wxStyledTextCtrl", "setSelectionEnd", 2}, // 3084
+ {wxStyledTextCtrl_GetSelectionEnd, "wxStyledTextCtrl", "getSelectionEnd", 1}, // 3085
+ {wxStyledTextCtrl_SetPrintMagnification, "wxStyledTextCtrl", "setPrintMagnification", 2}, // 3086
+ {wxStyledTextCtrl_GetPrintMagnification, "wxStyledTextCtrl", "getPrintMagnification", 1}, // 3087
+ {wxStyledTextCtrl_SetPrintColourMode, "wxStyledTextCtrl", "setPrintColourMode", 2}, // 3088
+ {wxStyledTextCtrl_GetPrintColourMode, "wxStyledTextCtrl", "getPrintColourMode", 1}, // 3089
+ {wxStyledTextCtrl_FindText, "wxStyledTextCtrl", "findText", 5}, // 3090
+ {wxStyledTextCtrl_FormatRange, "wxStyledTextCtrl", "formatRange", 8}, // 3091
+ {wxStyledTextCtrl_GetFirstVisibleLine, "wxStyledTextCtrl", "getFirstVisibleLine", 1}, // 3092
+ {wxStyledTextCtrl_GetLine, "wxStyledTextCtrl", "getLine", 2}, // 3093
+ {wxStyledTextCtrl_GetLineCount, "wxStyledTextCtrl", "getLineCount", 1}, // 3094
+ {wxStyledTextCtrl_SetMarginLeft, "wxStyledTextCtrl", "setMarginLeft", 2}, // 3095
+ {wxStyledTextCtrl_GetMarginLeft, "wxStyledTextCtrl", "getMarginLeft", 1}, // 3096
+ {wxStyledTextCtrl_SetMarginRight, "wxStyledTextCtrl", "setMarginRight", 2}, // 3097
+ {wxStyledTextCtrl_GetMarginRight, "wxStyledTextCtrl", "getMarginRight", 1}, // 3098
+ {wxStyledTextCtrl_GetModify, "wxStyledTextCtrl", "getModify", 1}, // 3099
+ {wxStyledTextCtrl_SetSelection, "wxStyledTextCtrl", "setSelection", 3}, // 3100
+ {wxStyledTextCtrl_GetSelectedText, "wxStyledTextCtrl", "getSelectedText", 1}, // 3101
+ {wxStyledTextCtrl_GetTextRange, "wxStyledTextCtrl", "getTextRange", 3}, // 3102
+ {wxStyledTextCtrl_HideSelection, "wxStyledTextCtrl", "hideSelection", 2}, // 3103
+ {wxStyledTextCtrl_LineFromPosition, "wxStyledTextCtrl", "lineFromPosition", 2}, // 3104
+ {wxStyledTextCtrl_PositionFromLine, "wxStyledTextCtrl", "positionFromLine", 2}, // 3105
+ {wxStyledTextCtrl_LineScroll, "wxStyledTextCtrl", "lineScroll", 3}, // 3106
+ {wxStyledTextCtrl_EnsureCaretVisible, "wxStyledTextCtrl", "ensureCaretVisible", 1}, // 3107
+ {wxStyledTextCtrl_ReplaceSelection, "wxStyledTextCtrl", "replaceSelection", 2}, // 3108
+ {wxStyledTextCtrl_SetReadOnly, "wxStyledTextCtrl", "setReadOnly", 2}, // 3109
+ {wxStyledTextCtrl_CanPaste, "wxStyledTextCtrl", "canPaste", 1}, // 3110
+ {wxStyledTextCtrl_CanUndo, "wxStyledTextCtrl", "canUndo", 1}, // 3111
+ {wxStyledTextCtrl_EmptyUndoBuffer, "wxStyledTextCtrl", "emptyUndoBuffer", 1}, // 3112
+ {wxStyledTextCtrl_Undo, "wxStyledTextCtrl", "undo", 1}, // 3113
+ {wxStyledTextCtrl_Cut, "wxStyledTextCtrl", "cut", 1}, // 3114
+ {wxStyledTextCtrl_Copy, "wxStyledTextCtrl", "copy", 1}, // 3115
+ {wxStyledTextCtrl_Paste, "wxStyledTextCtrl", "paste", 1}, // 3116
+ {wxStyledTextCtrl_Clear, "wxStyledTextCtrl", "clear", 1}, // 3117
+ {wxStyledTextCtrl_SetText, "wxStyledTextCtrl", "setText", 2}, // 3118
+ {wxStyledTextCtrl_GetText, "wxStyledTextCtrl", "getText", 1}, // 3119
+ {wxStyledTextCtrl_GetTextLength, "wxStyledTextCtrl", "getTextLength", 1}, // 3120
+ {wxStyledTextCtrl_GetOvertype, "wxStyledTextCtrl", "getOvertype", 1}, // 3121
+ {wxStyledTextCtrl_SetCaretWidth, "wxStyledTextCtrl", "setCaretWidth", 2}, // 3122
+ {wxStyledTextCtrl_GetCaretWidth, "wxStyledTextCtrl", "getCaretWidth", 1}, // 3123
+ {wxStyledTextCtrl_SetTargetStart, "wxStyledTextCtrl", "setTargetStart", 2}, // 3124
+ {wxStyledTextCtrl_GetTargetStart, "wxStyledTextCtrl", "getTargetStart", 1}, // 3125
+ {wxStyledTextCtrl_SetTargetEnd, "wxStyledTextCtrl", "setTargetEnd", 2}, // 3126
+ {wxStyledTextCtrl_GetTargetEnd, "wxStyledTextCtrl", "getTargetEnd", 1}, // 3127
+ {wxStyledTextCtrl_ReplaceTarget, "wxStyledTextCtrl", "replaceTarget", 2}, // 3128
+ {wxStyledTextCtrl_SearchInTarget, "wxStyledTextCtrl", "searchInTarget", 2}, // 3129
+ {wxStyledTextCtrl_SetSearchFlags, "wxStyledTextCtrl", "setSearchFlags", 2}, // 3130
+ {wxStyledTextCtrl_GetSearchFlags, "wxStyledTextCtrl", "getSearchFlags", 1}, // 3131
+ {wxStyledTextCtrl_CallTipShow, "wxStyledTextCtrl", "callTipShow", 3}, // 3132
+ {wxStyledTextCtrl_CallTipCancel, "wxStyledTextCtrl", "callTipCancel", 1}, // 3133
+ {wxStyledTextCtrl_CallTipActive, "wxStyledTextCtrl", "callTipActive", 1}, // 3134
+ {wxStyledTextCtrl_CallTipPosAtStart, "wxStyledTextCtrl", "callTipPosAtStart", 1}, // 3135
+ {wxStyledTextCtrl_CallTipSetHighlight, "wxStyledTextCtrl", "callTipSetHighlight", 3}, // 3136
+ {wxStyledTextCtrl_CallTipSetBackground, "wxStyledTextCtrl", "callTipSetBackground", 2}, // 3137
+ {wxStyledTextCtrl_CallTipSetForeground, "wxStyledTextCtrl", "callTipSetForeground", 2}, // 3138
+ {wxStyledTextCtrl_CallTipSetForegroundHighlight, "wxStyledTextCtrl", "callTipSetForegroundHighlight", 2}, // 3139
+ {wxStyledTextCtrl_CallTipUseStyle, "wxStyledTextCtrl", "callTipUseStyle", 2}, // 3140
+ {wxStyledTextCtrl_VisibleFromDocLine, "wxStyledTextCtrl", "visibleFromDocLine", 2}, // 3141
+ {wxStyledTextCtrl_DocLineFromVisible, "wxStyledTextCtrl", "docLineFromVisible", 2}, // 3142
+ {wxStyledTextCtrl_WrapCount, "wxStyledTextCtrl", "wrapCount", 2}, // 3143
+ {wxStyledTextCtrl_SetFoldLevel, "wxStyledTextCtrl", "setFoldLevel", 3}, // 3144
+ {wxStyledTextCtrl_GetFoldLevel, "wxStyledTextCtrl", "getFoldLevel", 2}, // 3145
+ {wxStyledTextCtrl_GetLastChild, "wxStyledTextCtrl", "getLastChild", 3}, // 3146
+ {wxStyledTextCtrl_GetFoldParent, "wxStyledTextCtrl", "getFoldParent", 2}, // 3147
+ {wxStyledTextCtrl_ShowLines, "wxStyledTextCtrl", "showLines", 3}, // 3148
+ {wxStyledTextCtrl_HideLines, "wxStyledTextCtrl", "hideLines", 3}, // 3149
+ {wxStyledTextCtrl_GetLineVisible, "wxStyledTextCtrl", "getLineVisible", 2}, // 3150
+ {wxStyledTextCtrl_SetFoldExpanded, "wxStyledTextCtrl", "setFoldExpanded", 3}, // 3151
+ {wxStyledTextCtrl_GetFoldExpanded, "wxStyledTextCtrl", "getFoldExpanded", 2}, // 3152
+ {wxStyledTextCtrl_ToggleFold, "wxStyledTextCtrl", "toggleFold", 2}, // 3153
+ {wxStyledTextCtrl_EnsureVisible, "wxStyledTextCtrl", "ensureVisible", 2}, // 3154
+ {wxStyledTextCtrl_SetFoldFlags, "wxStyledTextCtrl", "setFoldFlags", 2}, // 3155
+ {wxStyledTextCtrl_EnsureVisibleEnforcePolicy, "wxStyledTextCtrl", "ensureVisibleEnforcePolicy", 2}, // 3156
+ {wxStyledTextCtrl_SetTabIndents, "wxStyledTextCtrl", "setTabIndents", 2}, // 3157
+ {wxStyledTextCtrl_GetTabIndents, "wxStyledTextCtrl", "getTabIndents", 1}, // 3158
+ {wxStyledTextCtrl_SetBackSpaceUnIndents, "wxStyledTextCtrl", "setBackSpaceUnIndents", 2}, // 3159
+ {wxStyledTextCtrl_GetBackSpaceUnIndents, "wxStyledTextCtrl", "getBackSpaceUnIndents", 1}, // 3160
+ {wxStyledTextCtrl_SetMouseDwellTime, "wxStyledTextCtrl", "setMouseDwellTime", 2}, // 3161
+ {wxStyledTextCtrl_GetMouseDwellTime, "wxStyledTextCtrl", "getMouseDwellTime", 1}, // 3162
+ {wxStyledTextCtrl_WordStartPosition, "wxStyledTextCtrl", "wordStartPosition", 3}, // 3163
+ {wxStyledTextCtrl_WordEndPosition, "wxStyledTextCtrl", "wordEndPosition", 3}, // 3164
+ {wxStyledTextCtrl_SetWrapMode, "wxStyledTextCtrl", "setWrapMode", 2}, // 3165
+ {wxStyledTextCtrl_GetWrapMode, "wxStyledTextCtrl", "getWrapMode", 1}, // 3166
+ {wxStyledTextCtrl_SetWrapVisualFlags, "wxStyledTextCtrl", "setWrapVisualFlags", 2}, // 3167
+ {wxStyledTextCtrl_GetWrapVisualFlags, "wxStyledTextCtrl", "getWrapVisualFlags", 1}, // 3168
+ {wxStyledTextCtrl_SetWrapVisualFlagsLocation, "wxStyledTextCtrl", "setWrapVisualFlagsLocation", 2}, // 3169
+ {wxStyledTextCtrl_GetWrapVisualFlagsLocation, "wxStyledTextCtrl", "getWrapVisualFlagsLocation", 1}, // 3170
+ {wxStyledTextCtrl_SetWrapStartIndent, "wxStyledTextCtrl", "setWrapStartIndent", 2}, // 3171
+ {wxStyledTextCtrl_GetWrapStartIndent, "wxStyledTextCtrl", "getWrapStartIndent", 1}, // 3172
+ {wxStyledTextCtrl_SetLayoutCache, "wxStyledTextCtrl", "setLayoutCache", 2}, // 3173
+ {wxStyledTextCtrl_GetLayoutCache, "wxStyledTextCtrl", "getLayoutCache", 1}, // 3174
+ {wxStyledTextCtrl_SetScrollWidth, "wxStyledTextCtrl", "setScrollWidth", 2}, // 3175
+ {wxStyledTextCtrl_GetScrollWidth, "wxStyledTextCtrl", "getScrollWidth", 1}, // 3176
+ {wxStyledTextCtrl_TextWidth, "wxStyledTextCtrl", "textWidth", 3}, // 3177
+ {wxStyledTextCtrl_GetEndAtLastLine, "wxStyledTextCtrl", "getEndAtLastLine", 1}, // 3178
+ {wxStyledTextCtrl_TextHeight, "wxStyledTextCtrl", "textHeight", 2}, // 3179
+ {wxStyledTextCtrl_SetUseVerticalScrollBar, "wxStyledTextCtrl", "setUseVerticalScrollBar", 2}, // 3180
+ {wxStyledTextCtrl_GetUseVerticalScrollBar, "wxStyledTextCtrl", "getUseVerticalScrollBar", 1}, // 3181
+ {wxStyledTextCtrl_AppendText, "wxStyledTextCtrl", "appendText", 2}, // 3182
+ {wxStyledTextCtrl_GetTwoPhaseDraw, "wxStyledTextCtrl", "getTwoPhaseDraw", 1}, // 3183
+ {wxStyledTextCtrl_SetTwoPhaseDraw, "wxStyledTextCtrl", "setTwoPhaseDraw", 2}, // 3184
+ {wxStyledTextCtrl_TargetFromSelection, "wxStyledTextCtrl", "targetFromSelection", 1}, // 3185
+ {wxStyledTextCtrl_LinesJoin, "wxStyledTextCtrl", "linesJoin", 1}, // 3186
+ {wxStyledTextCtrl_LinesSplit, "wxStyledTextCtrl", "linesSplit", 2}, // 3187
+ {wxStyledTextCtrl_SetFoldMarginColour, "wxStyledTextCtrl", "setFoldMarginColour", 3}, // 3188
+ {wxStyledTextCtrl_SetFoldMarginHiColour, "wxStyledTextCtrl", "setFoldMarginHiColour", 3}, // 3189
+ {wxStyledTextCtrl_LineDown, "wxStyledTextCtrl", "lineDown", 1}, // 3190
+ {wxStyledTextCtrl_LineDownExtend, "wxStyledTextCtrl", "lineDownExtend", 1}, // 3191
+ {wxStyledTextCtrl_LineUp, "wxStyledTextCtrl", "lineUp", 1}, // 3192
+ {wxStyledTextCtrl_LineUpExtend, "wxStyledTextCtrl", "lineUpExtend", 1}, // 3193
+ {wxStyledTextCtrl_CharLeft, "wxStyledTextCtrl", "charLeft", 1}, // 3194
+ {wxStyledTextCtrl_CharLeftExtend, "wxStyledTextCtrl", "charLeftExtend", 1}, // 3195
+ {wxStyledTextCtrl_CharRight, "wxStyledTextCtrl", "charRight", 1}, // 3196
+ {wxStyledTextCtrl_CharRightExtend, "wxStyledTextCtrl", "charRightExtend", 1}, // 3197
+ {wxStyledTextCtrl_WordLeft, "wxStyledTextCtrl", "wordLeft", 1}, // 3198
+ {wxStyledTextCtrl_WordLeftExtend, "wxStyledTextCtrl", "wordLeftExtend", 1}, // 3199
+ {wxStyledTextCtrl_WordRight, "wxStyledTextCtrl", "wordRight", 1}, // 3200
+ {wxStyledTextCtrl_WordRightExtend, "wxStyledTextCtrl", "wordRightExtend", 1}, // 3201
+ {wxStyledTextCtrl_Home, "wxStyledTextCtrl", "home", 1}, // 3202
+ {wxStyledTextCtrl_HomeExtend, "wxStyledTextCtrl", "homeExtend", 1}, // 3203
+ {wxStyledTextCtrl_LineEnd, "wxStyledTextCtrl", "lineEnd", 1}, // 3204
+ {wxStyledTextCtrl_LineEndExtend, "wxStyledTextCtrl", "lineEndExtend", 1}, // 3205
+ {wxStyledTextCtrl_DocumentStart, "wxStyledTextCtrl", "documentStart", 1}, // 3206
+ {wxStyledTextCtrl_DocumentStartExtend, "wxStyledTextCtrl", "documentStartExtend", 1}, // 3207
+ {wxStyledTextCtrl_DocumentEnd, "wxStyledTextCtrl", "documentEnd", 1}, // 3208
+ {wxStyledTextCtrl_DocumentEndExtend, "wxStyledTextCtrl", "documentEndExtend", 1}, // 3209
+ {wxStyledTextCtrl_PageUp, "wxStyledTextCtrl", "pageUp", 1}, // 3210
+ {wxStyledTextCtrl_PageUpExtend, "wxStyledTextCtrl", "pageUpExtend", 1}, // 3211
+ {wxStyledTextCtrl_PageDown, "wxStyledTextCtrl", "pageDown", 1}, // 3212
+ {wxStyledTextCtrl_PageDownExtend, "wxStyledTextCtrl", "pageDownExtend", 1}, // 3213
+ {wxStyledTextCtrl_EditToggleOvertype, "wxStyledTextCtrl", "editToggleOvertype", 1}, // 3214
+ {wxStyledTextCtrl_Cancel, "wxStyledTextCtrl", "cancel", 1}, // 3215
+ {wxStyledTextCtrl_DeleteBack, "wxStyledTextCtrl", "deleteBack", 1}, // 3216
+ {wxStyledTextCtrl_Tab, "wxStyledTextCtrl", "tab", 1}, // 3217
+ {wxStyledTextCtrl_BackTab, "wxStyledTextCtrl", "backTab", 1}, // 3218
+ {wxStyledTextCtrl_NewLine, "wxStyledTextCtrl", "newLine", 1}, // 3219
+ {wxStyledTextCtrl_FormFeed, "wxStyledTextCtrl", "formFeed", 1}, // 3220
+ {wxStyledTextCtrl_VCHome, "wxStyledTextCtrl", "vCHome", 1}, // 3221
+ {wxStyledTextCtrl_VCHomeExtend, "wxStyledTextCtrl", "vCHomeExtend", 1}, // 3222
+ {wxStyledTextCtrl_ZoomIn, "wxStyledTextCtrl", "zoomIn", 1}, // 3223
+ {wxStyledTextCtrl_ZoomOut, "wxStyledTextCtrl", "zoomOut", 1}, // 3224
+ {wxStyledTextCtrl_DelWordLeft, "wxStyledTextCtrl", "delWordLeft", 1}, // 3225
+ {wxStyledTextCtrl_DelWordRight, "wxStyledTextCtrl", "delWordRight", 1}, // 3226
+ {wxStyledTextCtrl_LineCut, "wxStyledTextCtrl", "lineCut", 1}, // 3227
+ {wxStyledTextCtrl_LineDelete, "wxStyledTextCtrl", "lineDelete", 1}, // 3228
+ {wxStyledTextCtrl_LineTranspose, "wxStyledTextCtrl", "lineTranspose", 1}, // 3229
+ {wxStyledTextCtrl_LineDuplicate, "wxStyledTextCtrl", "lineDuplicate", 1}, // 3230
+ {wxStyledTextCtrl_LowerCase, "wxStyledTextCtrl", "lowerCase", 1}, // 3231
+ {wxStyledTextCtrl_UpperCase, "wxStyledTextCtrl", "upperCase", 1}, // 3232
+ {wxStyledTextCtrl_LineScrollDown, "wxStyledTextCtrl", "lineScrollDown", 1}, // 3233
+ {wxStyledTextCtrl_LineScrollUp, "wxStyledTextCtrl", "lineScrollUp", 1}, // 3234
+ {wxStyledTextCtrl_DeleteBackNotLine, "wxStyledTextCtrl", "deleteBackNotLine", 1}, // 3235
+ {wxStyledTextCtrl_HomeDisplay, "wxStyledTextCtrl", "homeDisplay", 1}, // 3236
+ {wxStyledTextCtrl_HomeDisplayExtend, "wxStyledTextCtrl", "homeDisplayExtend", 1}, // 3237
+ {wxStyledTextCtrl_LineEndDisplay, "wxStyledTextCtrl", "lineEndDisplay", 1}, // 3238
+ {wxStyledTextCtrl_LineEndDisplayExtend, "wxStyledTextCtrl", "lineEndDisplayExtend", 1}, // 3239
+ {wxStyledTextCtrl_HomeWrapExtend, "wxStyledTextCtrl", "homeWrapExtend", 1}, // 3240
+ {wxStyledTextCtrl_LineEndWrap, "wxStyledTextCtrl", "lineEndWrap", 1}, // 3241
+ {wxStyledTextCtrl_LineEndWrapExtend, "wxStyledTextCtrl", "lineEndWrapExtend", 1}, // 3242
+ {wxStyledTextCtrl_VCHomeWrap, "wxStyledTextCtrl", "vCHomeWrap", 1}, // 3243
+ {wxStyledTextCtrl_VCHomeWrapExtend, "wxStyledTextCtrl", "vCHomeWrapExtend", 1}, // 3244
+ {wxStyledTextCtrl_LineCopy, "wxStyledTextCtrl", "lineCopy", 1}, // 3245
+ {wxStyledTextCtrl_MoveCaretInsideView, "wxStyledTextCtrl", "moveCaretInsideView", 1}, // 3246
+ {wxStyledTextCtrl_LineLength, "wxStyledTextCtrl", "lineLength", 2}, // 3247
+ {wxStyledTextCtrl_BraceHighlight, "wxStyledTextCtrl", "braceHighlight", 3}, // 3248
+ {wxStyledTextCtrl_BraceBadLight, "wxStyledTextCtrl", "braceBadLight", 2}, // 3249
+ {wxStyledTextCtrl_BraceMatch, "wxStyledTextCtrl", "braceMatch", 2}, // 3250
+ {wxStyledTextCtrl_GetViewEOL, "wxStyledTextCtrl", "getViewEOL", 1}, // 3251
+ {wxStyledTextCtrl_SetViewEOL, "wxStyledTextCtrl", "setViewEOL", 2}, // 3252
+ {wxStyledTextCtrl_SetModEventMask, "wxStyledTextCtrl", "setModEventMask", 2}, // 3253
+ {wxStyledTextCtrl_GetEdgeColumn, "wxStyledTextCtrl", "getEdgeColumn", 1}, // 3254
+ {wxStyledTextCtrl_SetEdgeColumn, "wxStyledTextCtrl", "setEdgeColumn", 2}, // 3255
+ {wxStyledTextCtrl_SetEdgeMode, "wxStyledTextCtrl", "setEdgeMode", 2}, // 3256
+ {wxStyledTextCtrl_GetEdgeMode, "wxStyledTextCtrl", "getEdgeMode", 1}, // 3257
+ {wxStyledTextCtrl_GetEdgeColour, "wxStyledTextCtrl", "getEdgeColour", 1}, // 3258
+ {wxStyledTextCtrl_SetEdgeColour, "wxStyledTextCtrl", "setEdgeColour", 2}, // 3259
+ {wxStyledTextCtrl_SearchAnchor, "wxStyledTextCtrl", "searchAnchor", 1}, // 3260
+ {wxStyledTextCtrl_SearchNext, "wxStyledTextCtrl", "searchNext", 3}, // 3261
+ {wxStyledTextCtrl_SearchPrev, "wxStyledTextCtrl", "searchPrev", 3}, // 3262
+ {wxStyledTextCtrl_LinesOnScreen, "wxStyledTextCtrl", "linesOnScreen", 1}, // 3263
+ {wxStyledTextCtrl_UsePopUp, "wxStyledTextCtrl", "usePopUp", 2}, // 3264
+ {wxStyledTextCtrl_SelectionIsRectangle, "wxStyledTextCtrl", "selectionIsRectangle", 1}, // 3265
+ {wxStyledTextCtrl_SetZoom, "wxStyledTextCtrl", "setZoom", 2}, // 3266
+ {wxStyledTextCtrl_GetZoom, "wxStyledTextCtrl", "getZoom", 1}, // 3267
+ {wxStyledTextCtrl_GetModEventMask, "wxStyledTextCtrl", "getModEventMask", 1}, // 3268
+ {wxStyledTextCtrl_SetSTCFocus, "wxStyledTextCtrl", "setSTCFocus", 2}, // 3269
+ {wxStyledTextCtrl_GetSTCFocus, "wxStyledTextCtrl", "getSTCFocus", 1}, // 3270
+ {wxStyledTextCtrl_SetStatus, "wxStyledTextCtrl", "setStatus", 2}, // 3271
+ {wxStyledTextCtrl_GetStatus, "wxStyledTextCtrl", "getStatus", 1}, // 3272
+ {wxStyledTextCtrl_SetMouseDownCaptures, "wxStyledTextCtrl", "setMouseDownCaptures", 2}, // 3273
+ {wxStyledTextCtrl_GetMouseDownCaptures, "wxStyledTextCtrl", "getMouseDownCaptures", 1}, // 3274
+ {wxStyledTextCtrl_SetSTCCursor, "wxStyledTextCtrl", "setSTCCursor", 2}, // 3275
+ {wxStyledTextCtrl_GetSTCCursor, "wxStyledTextCtrl", "getSTCCursor", 1}, // 3276
+ {wxStyledTextCtrl_SetControlCharSymbol, "wxStyledTextCtrl", "setControlCharSymbol", 2}, // 3277
+ {wxStyledTextCtrl_GetControlCharSymbol, "wxStyledTextCtrl", "getControlCharSymbol", 1}, // 3278
+ {wxStyledTextCtrl_WordPartLeft, "wxStyledTextCtrl", "wordPartLeft", 1}, // 3279
+ {wxStyledTextCtrl_WordPartLeftExtend, "wxStyledTextCtrl", "wordPartLeftExtend", 1}, // 3280
+ {wxStyledTextCtrl_WordPartRight, "wxStyledTextCtrl", "wordPartRight", 1}, // 3281
+ {wxStyledTextCtrl_WordPartRightExtend, "wxStyledTextCtrl", "wordPartRightExtend", 1}, // 3282
+ {wxStyledTextCtrl_SetVisiblePolicy, "wxStyledTextCtrl", "setVisiblePolicy", 3}, // 3283
+ {wxStyledTextCtrl_DelLineLeft, "wxStyledTextCtrl", "delLineLeft", 1}, // 3284
+ {wxStyledTextCtrl_DelLineRight, "wxStyledTextCtrl", "delLineRight", 1}, // 3285
+ {wxStyledTextCtrl_GetXOffset, "wxStyledTextCtrl", "getXOffset", 1}, // 3286
+ {wxStyledTextCtrl_ChooseCaretX, "wxStyledTextCtrl", "chooseCaretX", 1}, // 3287
+ {wxStyledTextCtrl_SetXCaretPolicy, "wxStyledTextCtrl", "setXCaretPolicy", 3}, // 3288
+ {wxStyledTextCtrl_SetYCaretPolicy, "wxStyledTextCtrl", "setYCaretPolicy", 3}, // 3289
+ {wxStyledTextCtrl_GetPrintWrapMode, "wxStyledTextCtrl", "getPrintWrapMode", 1}, // 3290
+ {wxStyledTextCtrl_SetHotspotActiveForeground, "wxStyledTextCtrl", "setHotspotActiveForeground", 3}, // 3291
+ {wxStyledTextCtrl_SetHotspotActiveBackground, "wxStyledTextCtrl", "setHotspotActiveBackground", 3}, // 3292
+ {wxStyledTextCtrl_SetHotspotActiveUnderline, "wxStyledTextCtrl", "setHotspotActiveUnderline", 2}, // 3293
+ {wxStyledTextCtrl_SetHotspotSingleLine, "wxStyledTextCtrl", "setHotspotSingleLine", 2}, // 3294
+ {wxStyledTextCtrl_ParaDownExtend, "wxStyledTextCtrl", "paraDownExtend", 1}, // 3295
+ {wxStyledTextCtrl_ParaUp, "wxStyledTextCtrl", "paraUp", 1}, // 3296
+ {wxStyledTextCtrl_ParaUpExtend, "wxStyledTextCtrl", "paraUpExtend", 1}, // 3297
+ {wxStyledTextCtrl_PositionBefore, "wxStyledTextCtrl", "positionBefore", 2}, // 3298
+ {wxStyledTextCtrl_PositionAfter, "wxStyledTextCtrl", "positionAfter", 2}, // 3299
+ {wxStyledTextCtrl_CopyRange, "wxStyledTextCtrl", "copyRange", 3}, // 3300
+ {wxStyledTextCtrl_CopyText, "wxStyledTextCtrl", "copyText", 3}, // 3301
+ {wxStyledTextCtrl_SetSelectionMode, "wxStyledTextCtrl", "setSelectionMode", 2}, // 3302
+ {wxStyledTextCtrl_GetSelectionMode, "wxStyledTextCtrl", "getSelectionMode", 1}, // 3303
+ {wxStyledTextCtrl_LineDownRectExtend, "wxStyledTextCtrl", "lineDownRectExtend", 1}, // 3304
+ {wxStyledTextCtrl_LineUpRectExtend, "wxStyledTextCtrl", "lineUpRectExtend", 1}, // 3305
+ {wxStyledTextCtrl_CharLeftRectExtend, "wxStyledTextCtrl", "charLeftRectExtend", 1}, // 3306
+ {wxStyledTextCtrl_CharRightRectExtend, "wxStyledTextCtrl", "charRightRectExtend", 1}, // 3307
+ {wxStyledTextCtrl_HomeRectExtend, "wxStyledTextCtrl", "homeRectExtend", 1}, // 3308
+ {wxStyledTextCtrl_VCHomeRectExtend, "wxStyledTextCtrl", "vCHomeRectExtend", 1}, // 3309
+ {wxStyledTextCtrl_LineEndRectExtend, "wxStyledTextCtrl", "lineEndRectExtend", 1}, // 3310
+ {wxStyledTextCtrl_PageUpRectExtend, "wxStyledTextCtrl", "pageUpRectExtend", 1}, // 3311
+ {wxStyledTextCtrl_PageDownRectExtend, "wxStyledTextCtrl", "pageDownRectExtend", 1}, // 3312
+ {wxStyledTextCtrl_StutteredPageUp, "wxStyledTextCtrl", "stutteredPageUp", 1}, // 3313
+ {wxStyledTextCtrl_StutteredPageUpExtend, "wxStyledTextCtrl", "stutteredPageUpExtend", 1}, // 3314
+ {wxStyledTextCtrl_StutteredPageDown, "wxStyledTextCtrl", "stutteredPageDown", 1}, // 3315
+ {wxStyledTextCtrl_StutteredPageDownExtend, "wxStyledTextCtrl", "stutteredPageDownExtend", 1}, // 3316
+ {wxStyledTextCtrl_WordLeftEnd, "wxStyledTextCtrl", "wordLeftEnd", 1}, // 3317
+ {wxStyledTextCtrl_WordLeftEndExtend, "wxStyledTextCtrl", "wordLeftEndExtend", 1}, // 3318
+ {wxStyledTextCtrl_WordRightEnd, "wxStyledTextCtrl", "wordRightEnd", 1}, // 3319
+ {wxStyledTextCtrl_WordRightEndExtend, "wxStyledTextCtrl", "wordRightEndExtend", 1}, // 3320
+ {wxStyledTextCtrl_SetWhitespaceChars, "wxStyledTextCtrl", "setWhitespaceChars", 2}, // 3321
+ {wxStyledTextCtrl_SetCharsDefault, "wxStyledTextCtrl", "setCharsDefault", 1}, // 3322
+ {wxStyledTextCtrl_AutoCompGetCurrent, "wxStyledTextCtrl", "autoCompGetCurrent", 1}, // 3323
+ {wxStyledTextCtrl_Allocate, "wxStyledTextCtrl", "allocate", 2}, // 3324
+ {wxStyledTextCtrl_FindColumn, "wxStyledTextCtrl", "findColumn", 3}, // 3325
+ {wxStyledTextCtrl_GetCaretSticky, "wxStyledTextCtrl", "getCaretSticky", 1}, // 3326
+ {wxStyledTextCtrl_SetCaretSticky, "wxStyledTextCtrl", "setCaretSticky", 2}, // 3327
+ {wxStyledTextCtrl_ToggleCaretSticky, "wxStyledTextCtrl", "toggleCaretSticky", 1}, // 3328
+ {wxStyledTextCtrl_SetPasteConvertEndings, "wxStyledTextCtrl", "setPasteConvertEndings", 2}, // 3329
+ {wxStyledTextCtrl_GetPasteConvertEndings, "wxStyledTextCtrl", "getPasteConvertEndings", 1}, // 3330
+ {wxStyledTextCtrl_SelectionDuplicate, "wxStyledTextCtrl", "selectionDuplicate", 1}, // 3331
+ {wxStyledTextCtrl_SetCaretLineBackAlpha, "wxStyledTextCtrl", "setCaretLineBackAlpha", 2}, // 3332
+ {wxStyledTextCtrl_GetCaretLineBackAlpha, "wxStyledTextCtrl", "getCaretLineBackAlpha", 1}, // 3333
+ {wxStyledTextCtrl_StartRecord, "wxStyledTextCtrl", "startRecord", 1}, // 3334
+ {wxStyledTextCtrl_StopRecord, "wxStyledTextCtrl", "stopRecord", 1}, // 3335
+ {wxStyledTextCtrl_SetLexer, "wxStyledTextCtrl", "setLexer", 2}, // 3336
+ {wxStyledTextCtrl_GetLexer, "wxStyledTextCtrl", "getLexer", 1}, // 3337
+ {wxStyledTextCtrl_Colourise, "wxStyledTextCtrl", "colourise", 3}, // 3338
+ {wxStyledTextCtrl_SetProperty, "wxStyledTextCtrl", "setProperty", 3}, // 3339
+ {wxStyledTextCtrl_SetKeyWords, "wxStyledTextCtrl", "setKeyWords", 3}, // 3340
+ {wxStyledTextCtrl_SetLexerLanguage, "wxStyledTextCtrl", "setLexerLanguage", 2}, // 3341
+ {wxStyledTextCtrl_GetProperty, "wxStyledTextCtrl", "getProperty", 2}, // 3342
+ {wxStyledTextCtrl_GetStyleBitsNeeded, "wxStyledTextCtrl", "getStyleBitsNeeded", 1}, // 3343
+ {wxStyledTextCtrl_GetCurrentLine, "wxStyledTextCtrl", "getCurrentLine", 1}, // 3344
+ {wxStyledTextCtrl_StyleSetSpec, "wxStyledTextCtrl", "styleSetSpec", 3}, // 3345
+ {wxStyledTextCtrl_StyleSetFont, "wxStyledTextCtrl", "styleSetFont", 3}, // 3346
+ {wxStyledTextCtrl_StyleSetFontAttr, "wxStyledTextCtrl", "styleSetFontAttr", 8}, // 3347
+ {wxStyledTextCtrl_StyleSetCharacterSet, "wxStyledTextCtrl", "styleSetCharacterSet", 3}, // 3348
+ {wxStyledTextCtrl_StyleSetFontEncoding, "wxStyledTextCtrl", "styleSetFontEncoding", 3}, // 3349
+ {wxStyledTextCtrl_CmdKeyExecute, "wxStyledTextCtrl", "cmdKeyExecute", 2}, // 3350
+ {wxStyledTextCtrl_SetMargins, "wxStyledTextCtrl", "setMargins", 3}, // 3351
+ {wxStyledTextCtrl_GetSelection, "wxStyledTextCtrl", "getSelection", 1}, // 3352
+ {wxStyledTextCtrl_PointFromPosition, "wxStyledTextCtrl", "pointFromPosition", 2}, // 3353
+ {wxStyledTextCtrl_ScrollToLine, "wxStyledTextCtrl", "scrollToLine", 2}, // 3354
+ {wxStyledTextCtrl_ScrollToColumn, "wxStyledTextCtrl", "scrollToColumn", 2}, // 3355
+ {wxStyledTextCtrl_SetVScrollBar, "wxStyledTextCtrl", "setVScrollBar", 2}, // 3356
+ {wxStyledTextCtrl_SetHScrollBar, "wxStyledTextCtrl", "setHScrollBar", 2}, // 3357
+ {wxStyledTextCtrl_GetLastKeydownProcessed, "wxStyledTextCtrl", "getLastKeydownProcessed", 1}, // 3358
+ {wxStyledTextCtrl_SetLastKeydownProcessed, "wxStyledTextCtrl", "setLastKeydownProcessed", 2}, // 3359
+ {wxStyledTextCtrl_SaveFile, "wxStyledTextCtrl", "saveFile", 2}, // 3360
+ {wxStyledTextCtrl_LoadFile, "wxStyledTextCtrl", "loadFile", 2}, // 3361
+ {wxStyledTextCtrl_DoDragOver, "wxStyledTextCtrl", "doDragOver", 4}, // 3362
+ {wxStyledTextCtrl_DoDropText, "wxStyledTextCtrl", "doDropText", 4}, // 3363
+ {wxStyledTextCtrl_GetUseAntiAliasing, "wxStyledTextCtrl", "getUseAntiAliasing", 1}, // 3364
+ {wxStyledTextCtrl_AddTextRaw, "wxStyledTextCtrl", "addTextRaw", 3}, // 3365
+ {wxStyledTextCtrl_InsertTextRaw, "wxStyledTextCtrl", "insertTextRaw", 3}, // 3366
+ {wxStyledTextCtrl_GetCurLineRaw, "wxStyledTextCtrl", "getCurLineRaw", 1}, // 3367
+ {wxStyledTextCtrl_GetLineRaw, "wxStyledTextCtrl", "getLineRaw", 2}, // 3368
+ {wxStyledTextCtrl_GetSelectedTextRaw, "wxStyledTextCtrl", "getSelectedTextRaw", 1}, // 3369
+ {wxStyledTextCtrl_GetTextRangeRaw, "wxStyledTextCtrl", "getTextRangeRaw", 3}, // 3370
+ {wxStyledTextCtrl_SetTextRaw, "wxStyledTextCtrl", "setTextRaw", 2}, // 3371
+ {wxStyledTextCtrl_GetTextRaw, "wxStyledTextCtrl", "getTextRaw", 1}, // 3372
+ {wxStyledTextCtrl_AppendTextRaw, "wxStyledTextCtrl", "appendTextRaw", 3}, // 3373
+ {wxArtProvider_GetBitmap, "wxArtProvider", "getBitmap", 2}, // 3374
+ {wxArtProvider_GetIcon, "wxArtProvider", "getIcon", 2}, // 3375
+ {wxTreeEvent_GetKeyCode, "wxTreeEvent", "getKeyCode", 1}, // 3376
+ {wxTreeEvent_GetItem, "wxTreeEvent", "getItem", 1}, // 3377
+ {wxTreeEvent_GetKeyEvent, "wxTreeEvent", "getKeyEvent", 1}, // 3378
+ {wxTreeEvent_GetLabel, "wxTreeEvent", "getLabel", 1}, // 3379
+ {wxTreeEvent_GetOldItem, "wxTreeEvent", "getOldItem", 1}, // 3380
+ {wxTreeEvent_GetPoint, "wxTreeEvent", "getPoint", 1}, // 3381
+ {wxTreeEvent_IsEditCancelled, "wxTreeEvent", "isEditCancelled", 1}, // 3382
+ {wxTreeEvent_SetToolTip, "wxTreeEvent", "setToolTip", 2}, // 3383
+ {wxBookCtrlEvent_GetOldSelection, "wxBookCtrlEvent", "getOldSelection", 1}, // 3384
+ {wxBookCtrlEvent_GetSelection, "wxBookCtrlEvent", "getSelection", 1}, // 3385
+ {wxBookCtrlEvent_SetOldSelection, "wxBookCtrlEvent", "setOldSelection", 2}, // 3386
+ {wxBookCtrlEvent_SetSelection, "wxBookCtrlEvent", "setSelection", 2}, // 3387
+ {wxFileDataObject_new, "wxFileDataObject", "new", 0}, // 3388
+ {wxFileDataObject_AddFile, "wxFileDataObject", "addFile", 2}, // 3389
+ {wxFileDataObject_GetFilenames, "wxFileDataObject", "getFilenames", 1}, // 3390
+ {wxFileDataObject_destroy, "wxFileDataObject", "'Destroy'", 1}, // 3391
+ {wxTextDataObject_new, "wxTextDataObject", "new", 1}, // 3392
+ {wxTextDataObject_GetTextLength, "wxTextDataObject", "getTextLength", 1}, // 3393
+ {wxTextDataObject_GetText, "wxTextDataObject", "getText", 1}, // 3394
+ {wxTextDataObject_SetText, "wxTextDataObject", "setText", 2}, // 3395
+ {wxTextDataObject_destroy, "wxTextDataObject", "'Destroy'", 1}, // 3396
+ {wxBitmapDataObject_new_1_1, "wxBitmapDataObject", "new", 1}, // 3397
+ {wxBitmapDataObject_new_1_0, "wxBitmapDataObject", "new", 1}, // 3398
+ {wxBitmapDataObject_GetBitmap, "wxBitmapDataObject", "getBitmap", 1}, // 3399
+ {wxBitmapDataObject_SetBitmap, "wxBitmapDataObject", "setBitmap", 2}, // 3400
+ {wxBitmapDataObject_destroy, "wxBitmapDataObject", "'Destroy'", 1}, // 3401
+ {wxClipboard_new, "wxClipboard", "new", 0}, // 3402
+ {NULL, "wxClipboard", "destroy", 1}, // 3403 obj destructor wxClipboard_destruct
+ {wxClipboard_AddData, "wxClipboard", "addData", 2}, // 3404
+ {wxClipboard_Clear, "wxClipboard", "clear", 1}, // 3405
+ {wxClipboard_Close, "wxClipboard", "close", 1}, // 3406
+ {wxClipboard_Flush, "wxClipboard", "flush", 1}, // 3407
+ {wxClipboard_GetData, "wxClipboard", "getData", 2}, // 3408
+ {wxClipboard_IsOpened, "wxClipboard", "isOpened", 1}, // 3409
+ {wxClipboard_Open, "wxClipboard", "open", 1}, // 3410
+ {wxClipboard_SetData, "wxClipboard", "setData", 2}, // 3411
+ {wxClipboard_UsePrimarySelection, "wxClipboard", "usePrimarySelection", 2}, // 3412
+ {wxClipboard_IsSupported, "wxClipboard", "isSupported", 2}, // 3413
+ {wxClipboard_Get, "wxClipboard", "get", 0}, // 3414
+ {wxSpinEvent_GetPosition, "wxSpinEvent", "getPosition", 1}, // 3415
+ {wxSpinEvent_SetPosition, "wxSpinEvent", "setPosition", 2}, // 3416
+ {wxSplitterWindow_new_0, "wxSplitterWindow", "new", 0}, // 3417
+ {wxSplitterWindow_new_2, "wxSplitterWindow", "new", 2}, // 3418
+ {NULL, "wxSplitterWindow", "destroy", 1}, // 3419 obj destructor wxSplitterWindow_destruct
+ {wxSplitterWindow_Create, "wxSplitterWindow", "create", 3}, // 3420
+ {wxSplitterWindow_GetMinimumPaneSize, "wxSplitterWindow", "getMinimumPaneSize", 1}, // 3421
+ {wxSplitterWindow_GetSashGravity, "wxSplitterWindow", "getSashGravity", 1}, // 3422
+ {wxSplitterWindow_GetSashPosition, "wxSplitterWindow", "getSashPosition", 1}, // 3423
+ {wxSplitterWindow_GetSplitMode, "wxSplitterWindow", "getSplitMode", 1}, // 3424
+ {wxSplitterWindow_GetWindow1, "wxSplitterWindow", "getWindow1", 1}, // 3425
+ {wxSplitterWindow_GetWindow2, "wxSplitterWindow", "getWindow2", 1}, // 3426
+ {wxSplitterWindow_Initialize, "wxSplitterWindow", "initialize", 2}, // 3427
+ {wxSplitterWindow_IsSplit, "wxSplitterWindow", "isSplit", 1}, // 3428
+ {wxSplitterWindow_ReplaceWindow, "wxSplitterWindow", "replaceWindow", 3}, // 3429
+ {wxSplitterWindow_SetSashGravity, "wxSplitterWindow", "setSashGravity", 2}, // 3430
+ {wxSplitterWindow_SetSashPosition, "wxSplitterWindow", "setSashPosition", 3}, // 3431
+ {wxSplitterWindow_SetMinimumPaneSize, "wxSplitterWindow", "setMinimumPaneSize", 2}, // 3432
+ {wxSplitterWindow_SetSplitMode, "wxSplitterWindow", "setSplitMode", 2}, // 3433
+ {wxSplitterWindow_SplitHorizontally, "wxSplitterWindow", "splitHorizontally", 4}, // 3434
+ {wxSplitterWindow_SplitVertically, "wxSplitterWindow", "splitVertically", 4}, // 3435
+ {wxSplitterWindow_Unsplit, "wxSplitterWindow", "unsplit", 2}, // 3436
+ {wxSplitterWindow_UpdateSize, "wxSplitterWindow", "updateSize", 1}, // 3437
+ {wxSplitterEvent_GetSashPosition, "wxSplitterEvent", "getSashPosition", 1}, // 3438
+ {wxSplitterEvent_GetX, "wxSplitterEvent", "getX", 1}, // 3439
+ {wxSplitterEvent_GetY, "wxSplitterEvent", "getY", 1}, // 3440
+ {wxSplitterEvent_GetWindowBeingRemoved, "wxSplitterEvent", "getWindowBeingRemoved", 1}, // 3441
+ {wxSplitterEvent_SetSashPosition, "wxSplitterEvent", "setSashPosition", 2}, // 3442
+ {wxHtmlWindow_new_0, "wxHtmlWindow", "new", 0}, // 3443
+ {wxHtmlWindow_new_2, "wxHtmlWindow", "new", 2}, // 3444
+ {wxHtmlWindow_AppendToPage, "wxHtmlWindow", "appendToPage", 2}, // 3445
+ {wxHtmlWindow_GetOpenedAnchor, "wxHtmlWindow", "getOpenedAnchor", 1}, // 3446
+ {wxHtmlWindow_GetOpenedPage, "wxHtmlWindow", "getOpenedPage", 1}, // 3447
+ {wxHtmlWindow_GetOpenedPageTitle, "wxHtmlWindow", "getOpenedPageTitle", 1}, // 3448
+ {wxHtmlWindow_GetRelatedFrame, "wxHtmlWindow", "getRelatedFrame", 1}, // 3449
+ {wxHtmlWindow_HistoryBack, "wxHtmlWindow", "historyBack", 1}, // 3450
+ {wxHtmlWindow_HistoryCanBack, "wxHtmlWindow", "historyCanBack", 1}, // 3451
+ {wxHtmlWindow_HistoryCanForward, "wxHtmlWindow", "historyCanForward", 1}, // 3452
+ {wxHtmlWindow_HistoryClear, "wxHtmlWindow", "historyClear", 1}, // 3453
+ {wxHtmlWindow_HistoryForward, "wxHtmlWindow", "historyForward", 1}, // 3454
+ {wxHtmlWindow_LoadFile, "wxHtmlWindow", "loadFile", 2}, // 3455
+ {wxHtmlWindow_LoadPage, "wxHtmlWindow", "loadPage", 2}, // 3456
+ {wxHtmlWindow_SelectAll, "wxHtmlWindow", "selectAll", 1}, // 3457
+ {wxHtmlWindow_SelectionToText, "wxHtmlWindow", "selectionToText", 1}, // 3458
+ {wxHtmlWindow_SelectLine, "wxHtmlWindow", "selectLine", 2}, // 3459
+ {wxHtmlWindow_SelectWord, "wxHtmlWindow", "selectWord", 2}, // 3460
+ {wxHtmlWindow_SetBorders, "wxHtmlWindow", "setBorders", 2}, // 3461
+ {wxHtmlWindow_SetFonts, "wxHtmlWindow", "setFonts", 4}, // 3462
+ {wxHtmlWindow_SetPage, "wxHtmlWindow", "setPage", 2}, // 3463
+ {wxHtmlWindow_SetRelatedFrame, "wxHtmlWindow", "setRelatedFrame", 3}, // 3464
+ {wxHtmlWindow_SetRelatedStatusBar_1, "wxHtmlWindow", "setRelatedStatusBar", 2}, // 3465
+ {wxHtmlWindow_SetRelatedStatusBar_2, "wxHtmlWindow", "setRelatedStatusBar", 3}, // 3466
+ {wxHtmlWindow_ToText, "wxHtmlWindow", "toText", 1}, // 3467
+ {NULL, "wxHtmlWindow", "'Destroy'", 1}, // 3468 obj destructor wxHtmlWindow_destroy
+ {wxHtmlLinkEvent_GetLinkInfo, "wxHtmlLinkEvent", "getLinkInfo", 1}, // 3469
+ {wxSystemSettings_GetColour, "wxSystemSettings", "getColour", 1}, // 3470
+ {wxSystemSettings_GetFont, "wxSystemSettings", "getFont", 1}, // 3471
+ {wxSystemSettings_GetMetric, "wxSystemSettings", "getMetric", 2}, // 3472
+ {wxSystemSettings_GetScreenType, "wxSystemSettings", "getScreenType", 0}, // 3473
+ {wxSystemOptions_GetOption, "wxSystemOptions", "getOption", 1}, // 3474
+ {wxSystemOptions_GetOptionInt, "wxSystemOptions", "getOptionInt", 1}, // 3475
+ {wxSystemOptions_HasOption, "wxSystemOptions", "hasOption", 1}, // 3476
+ {wxSystemOptions_IsFalse, "wxSystemOptions", "isFalse", 1}, // 3477
+ {wxSystemOptions_SetOption_2_1, "wxSystemOptions", "setOption", 2}, // 3478
+ {wxSystemOptions_SetOption_2_0, "wxSystemOptions", "setOption", 2}, // 3479
+ {wxAuiNotebookEvent_SetSelection, "wxAuiNotebookEvent", "setSelection", 2}, // 3480
+ {wxAuiNotebookEvent_GetSelection, "wxAuiNotebookEvent", "getSelection", 1}, // 3481
+ {wxAuiNotebookEvent_SetOldSelection, "wxAuiNotebookEvent", "setOldSelection", 2}, // 3482
+ {wxAuiNotebookEvent_GetOldSelection, "wxAuiNotebookEvent", "getOldSelection", 1}, // 3483
+ {wxAuiNotebookEvent_SetDragSource, "wxAuiNotebookEvent", "setDragSource", 2}, // 3484
+ {wxAuiNotebookEvent_GetDragSource, "wxAuiNotebookEvent", "getDragSource", 1}, // 3485
+ {wxAuiManagerEvent_SetManager, "wxAuiManagerEvent", "setManager", 2}, // 3486
+ {wxAuiManagerEvent_GetManager, "wxAuiManagerEvent", "getManager", 1}, // 3487
+ {wxAuiManagerEvent_SetPane, "wxAuiManagerEvent", "setPane", 2}, // 3488
+ {wxAuiManagerEvent_GetPane, "wxAuiManagerEvent", "getPane", 1}, // 3489
+ {wxAuiManagerEvent_SetButton, "wxAuiManagerEvent", "setButton", 2}, // 3490
+ {wxAuiManagerEvent_GetButton, "wxAuiManagerEvent", "getButton", 1}, // 3491
+ {wxAuiManagerEvent_SetDC, "wxAuiManagerEvent", "setDC", 2}, // 3492
+ {wxAuiManagerEvent_GetDC, "wxAuiManagerEvent", "getDC", 1}, // 3493
+ {wxAuiManagerEvent_Veto, "wxAuiManagerEvent", "veto", 2}, // 3494
+ {wxAuiManagerEvent_GetVeto, "wxAuiManagerEvent", "getVeto", 1}, // 3495
+ {wxAuiManagerEvent_SetCanVeto, "wxAuiManagerEvent", "setCanVeto", 2}, // 3496
+ {wxAuiManagerEvent_CanVeto, "wxAuiManagerEvent", "canVeto", 1}, // 3497
+ {wxLogNull_new, "wxLogNull", "new", 0}, // 3498
+ {wxLogNull_destruct, "wxLogNull", "destroy", 1}, // 3499
+ {wxTaskBarIcon_new, "wxTaskBarIcon", "new", 1}, // 3500
+ {NULL, "wxTaskBarIcon", "destroy", 1}, // 3501 obj destructor wxTaskBarIcon_destruct
+ {wxTaskBarIcon_PopupMenu, "wxTaskBarIcon", "popupMenu", 2}, // 3502
+ {wxTaskBarIcon_RemoveIcon, "wxTaskBarIcon", "removeIcon", 1}, // 3503
+ {wxTaskBarIcon_SetIcon, "wxTaskBarIcon", "setIcon", 3}, // 3504
+ {wxLocale_new_0, "wxLocale", "new", 0}, // 3505
+ {wxLocale_new_2_0, "wxLocale", "new", 2}, // 3506
+ {wxLocale_new_2_1, "wxLocale", "new", 2}, // 3507
+ {wxLocale_destruct, "wxLocale", "destroy", 1}, // 3508
+ {wxLocale_Init_1, "wxLocale", "init", 2}, // 3509
+ {wxLocale_Init_2, "wxLocale", "init", 3}, // 3510
+ {wxLocale_AddCatalog_1, "wxLocale", "addCatalog", 2}, // 3511
+ {wxLocale_AddCatalog_2, "wxLocale", "addCatalog", 3}, // 3512
+ {wxLocale_AddCatalog_3, "wxLocale", "addCatalog", 4}, // 3513
+ {wxLocale_AddCatalogLookupPathPrefix, "wxLocale", "addCatalogLookupPathPrefix", 1}, // 3514
+ {wxLocale_GetCanonicalName, "wxLocale", "getCanonicalName", 1}, // 3515
+ {wxLocale_GetLanguage, "wxLocale", "getLanguage", 1}, // 3516
+ {wxLocale_GetLanguageName, "wxLocale", "getLanguageName", 1}, // 3517
+ {wxLocale_GetLocale, "wxLocale", "getLocale", 1}, // 3518
+ {wxLocale_GetName, "wxLocale", "getName", 1}, // 3519
+ {wxLocale_GetString_2, "wxLocale", "getString", 3}, // 3520
+ {wxLocale_GetString_4, "wxLocale", "getString", 5}, // 3521
+ {wxLocale_GetHeaderValue, "wxLocale", "getHeaderValue", 3}, // 3522
+ {wxLocale_GetSysName, "wxLocale", "getSysName", 1}, // 3523
+ {wxLocale_GetSystemEncoding, "wxLocale", "getSystemEncoding", 0}, // 3524
+ {wxLocale_GetSystemEncodingName, "wxLocale", "getSystemEncodingName", 0}, // 3525
+ {wxLocale_GetSystemLanguage, "wxLocale", "getSystemLanguage", 0}, // 3526
+ {wxLocale_IsLoaded, "wxLocale", "isLoaded", 2}, // 3527
+ {wxLocale_IsOk, "wxLocale", "isOk", 1}, // 3528
+ {wxActivateEvent_GetActive, "wxActivateEvent", "getActive", 1}, // 3529
#if wxUSE_POPUPWIN
- {wxPopupWindow_new_0, "wxPopupWindow", "new", 0}, // 3527
+ {wxPopupWindow_new_0, "wxPopupWindow", "new", 0}, // 3530
#else
- {NULL, "wxPopupWindow", "new", 0}, // 3527
+ {NULL, "wxPopupWindow", "new", 0}, // 3530
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupWindow_new_2, "wxPopupWindow", "new", 2}, // 3528
+ {wxPopupWindow_new_2, "wxPopupWindow", "new", 2}, // 3531
#else
- {NULL, "wxPopupWindow", "new", 0}, // 3528
+ {NULL, "wxPopupWindow", "new", 0}, // 3531
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupWindow_Create, "wxPopupWindow", "create", 3}, // 3529
+ {wxPopupWindow_Create, "wxPopupWindow", "create", 3}, // 3532
#else
- {NULL, "wxPopupWindow", "create", 0}, // 3529
+ {NULL, "wxPopupWindow", "create", 0}, // 3532
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupWindow_Position, "wxPopupWindow", "position", 3}, // 3530
+ {wxPopupWindow_Position, "wxPopupWindow", "position", 3}, // 3533
#else
- {NULL, "wxPopupWindow", "position", 0}, // 3530
+ {NULL, "wxPopupWindow", "position", 0}, // 3533
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {NULL, "wxPopupWindow", "'Destroy'", 1}, // 3531 obj destructor wxPopupWindow_destroy
+ {NULL, "wxPopupWindow", "'Destroy'", 1}, // 3534 obj destructor wxPopupWindow_destroy
#else
- {NULL, "wxPopupWindow", "'Destroy'", 0}, // 3531
+ {NULL, "wxPopupWindow", "'Destroy'", 0}, // 3534
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupTransientWindow_new_0, "wxPopupTransientWindow", "new", 0}, // 3532
+ {wxPopupTransientWindow_new_0, "wxPopupTransientWindow", "new", 0}, // 3535
#else
- {NULL, "wxPopupTransientWindow", "new", 0}, // 3532
+ {NULL, "wxPopupTransientWindow", "new", 0}, // 3535
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupTransientWindow_new_2, "wxPopupTransientWindow", "new", 2}, // 3533
+ {wxPopupTransientWindow_new_2, "wxPopupTransientWindow", "new", 2}, // 3536
#else
- {NULL, "wxPopupTransientWindow", "new", 0}, // 3533
+ {NULL, "wxPopupTransientWindow", "new", 0}, // 3536
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupTransientWindow_Popup, "wxPopupTransientWindow", "popup", 2}, // 3534
+ {wxPopupTransientWindow_Popup, "wxPopupTransientWindow", "popup", 2}, // 3537
#else
- {NULL, "wxPopupTransientWindow", "popup", 0}, // 3534
+ {NULL, "wxPopupTransientWindow", "popup", 0}, // 3537
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupTransientWindow_Dismiss, "wxPopupTransientWindow", "dismiss", 1}, // 3535
+ {wxPopupTransientWindow_Dismiss, "wxPopupTransientWindow", "dismiss", 1}, // 3538
#else
- {NULL, "wxPopupTransientWindow", "dismiss", 0}, // 3535
+ {NULL, "wxPopupTransientWindow", "dismiss", 0}, // 3538
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {NULL, "wxPopupTransientWindow", "'Destroy'", 1}, // 3536 obj destructor wxPopupTransientWindow_destroy
+ {NULL, "wxPopupTransientWindow", "'Destroy'", 1}, // 3539 obj destructor wxPopupTransientWindow_destroy
#else
- {NULL, "wxPopupTransientWindow", "'Destroy'", 0}, // 3536
+ {NULL, "wxPopupTransientWindow", "'Destroy'", 0}, // 3539
#endif // wxUSE_POPUPWIN
- {wxOverlay_new, "wxOverlay", "new", 0}, // 3537
- {wxOverlay_destruct, "wxOverlay", "destroy", 1}, // 3538
- {wxOverlay_Reset, "wxOverlay", "reset", 1}, // 3539
- {wxDCOverlay_new_6, "wxDCOverlay", "new", 6}, // 3540
- {wxDCOverlay_new_2, "wxDCOverlay", "new", 2}, // 3541
- {wxDCOverlay_destruct, "wxDCOverlay", "destroy", 1}, // 3542
- {wxDCOverlay_Clear, "wxDCOverlay", "clear", 1}, // 3543
- {wxDropFilesEvent_GetPosition, "wxDropFilesEvent", "getPosition", 1}, // 3544
- {wxDropFilesEvent_GetNumberOfFiles, "wxDropFilesEvent", "getNumberOfFiles", 1}, // 3545
- {wxDropFilesEvent_GetFiles, "wxDropFilesEvent", "getFiles", 1}, // 3546
+ {wxOverlay_new, "wxOverlay", "new", 0}, // 3540
+ {wxOverlay_destruct, "wxOverlay", "destroy", 1}, // 3541
+ {wxOverlay_Reset, "wxOverlay", "reset", 1}, // 3542
+ {wxDCOverlay_new_6, "wxDCOverlay", "new", 6}, // 3543
+ {wxDCOverlay_new_2, "wxDCOverlay", "new", 2}, // 3544
+ {wxDCOverlay_destruct, "wxDCOverlay", "destroy", 1}, // 3545
+ {wxDCOverlay_Clear, "wxDCOverlay", "clear", 1}, // 3546
+ {wxDropFilesEvent_GetPosition, "wxDropFilesEvent", "getPosition", 1}, // 3547
+ {wxDropFilesEvent_GetNumberOfFiles, "wxDropFilesEvent", "getNumberOfFiles", 1}, // 3548
+ {wxDropFilesEvent_GetFiles, "wxDropFilesEvent", "getFiles", 1}, // 3549
#if wxUSE_DISPLAY
- {wxDisplay_new_0, "wxDisplay", "new", 0}, // 3547
+ {wxDisplay_new_0, "wxDisplay", "new", 0}, // 3550
#else
- {NULL, "wxDisplay", "new", 0}, // 3547
+ {NULL, "wxDisplay", "new", 0}, // 3550
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_new_1_0, "wxDisplay", "new", 1}, // 3548
+ {wxDisplay_new_1_0, "wxDisplay", "new", 1}, // 3551
#else
- {NULL, "wxDisplay", "new", 0}, // 3548
+ {NULL, "wxDisplay", "new", 0}, // 3551
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY && wxCHECK_VERSION(3,1,3)
- {wxDisplay_new_1_1, "wxDisplay", "new", 1}, // 3549
+ {wxDisplay_new_1_1, "wxDisplay", "new", 1}, // 3552
#else
- {NULL, "wxDisplay", "new", 0}, // 3549
+ {NULL, "wxDisplay", "new", 0}, // 3552
#endif // wxUSE_DISPLAY && wxCHECK_VERSION(3,1,3)
#if wxUSE_DISPLAY
- {wxDisplay_destruct, "wxDisplay", "destroy", 1}, // 3550
+ {wxDisplay_destruct, "wxDisplay", "destroy", 1}, // 3553
#else
- {NULL, "wxDisplay", "destroy", 0}, // 3550
+ {NULL, "wxDisplay", "destroy", 0}, // 3553
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_IsOk, "wxDisplay", "isOk", 1}, // 3551
+ {wxDisplay_IsOk, "wxDisplay", "isOk", 1}, // 3554
#else
- {NULL, "wxDisplay", "isOk", 0}, // 3551
+ {NULL, "wxDisplay", "isOk", 0}, // 3554
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetClientArea, "wxDisplay", "getClientArea", 1}, // 3552
+ {wxDisplay_GetClientArea, "wxDisplay", "getClientArea", 1}, // 3555
#else
- {NULL, "wxDisplay", "getClientArea", 0}, // 3552
+ {NULL, "wxDisplay", "getClientArea", 0}, // 3555
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetGeometry, "wxDisplay", "getGeometry", 1}, // 3553
+ {wxDisplay_GetGeometry, "wxDisplay", "getGeometry", 1}, // 3556
#else
- {NULL, "wxDisplay", "getGeometry", 0}, // 3553
+ {NULL, "wxDisplay", "getGeometry", 0}, // 3556
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetName, "wxDisplay", "getName", 1}, // 3554
+ {wxDisplay_GetName, "wxDisplay", "getName", 1}, // 3557
#else
- {NULL, "wxDisplay", "getName", 0}, // 3554
+ {NULL, "wxDisplay", "getName", 0}, // 3557
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_IsPrimary, "wxDisplay", "isPrimary", 1}, // 3555
+ {wxDisplay_IsPrimary, "wxDisplay", "isPrimary", 1}, // 3558
#else
- {NULL, "wxDisplay", "isPrimary", 0}, // 3555
+ {NULL, "wxDisplay", "isPrimary", 0}, // 3558
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetCount, "wxDisplay", "getCount", 0}, // 3556
+ {wxDisplay_GetCount, "wxDisplay", "getCount", 0}, // 3559
#else
- {NULL, "wxDisplay", "getCount", 0}, // 3556
+ {NULL, "wxDisplay", "getCount", 0}, // 3559
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetFromPoint, "wxDisplay", "getFromPoint", 1}, // 3557
+ {wxDisplay_GetFromPoint, "wxDisplay", "getFromPoint", 1}, // 3560
#else
- {NULL, "wxDisplay", "getFromPoint", 0}, // 3557
+ {NULL, "wxDisplay", "getFromPoint", 0}, // 3560
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetFromWindow, "wxDisplay", "getFromWindow", 1}, // 3558
+ {wxDisplay_GetFromWindow, "wxDisplay", "getFromWindow", 1}, // 3561
#else
- {NULL, "wxDisplay", "getFromWindow", 0}, // 3558
+ {NULL, "wxDisplay", "getFromWindow", 0}, // 3561
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY && wxCHECK_VERSION(3,1,2)
- {wxDisplay_GetPPI, "wxDisplay", "getPPI", 1}, // 3559
+ {wxDisplay_GetPPI, "wxDisplay", "getPPI", 1}, // 3562
#else
- {NULL, "wxDisplay", "getPPI", 0}, // 3559
+ {NULL, "wxDisplay", "getPPI", 0}, // 3562
#endif // wxUSE_DISPLAY && wxCHECK_VERSION(3,1,2)
#if wxUSE_GRAPHICS_CONTEXT
- {wxGCDC_new_1, "wxGCDC", "new", 1}, // 3560
+ {wxGCDC_new_1, "wxGCDC", "new", 1}, // 3563
#else
- {NULL, "wxGCDC", "new", 0}, // 3560
+ {NULL, "wxGCDC", "new", 0}, // 3563
#endif // wxUSE_GRAPHICS_CONTEXT
- {NULL, "", "", 0}, // 3561
- {NULL, "", "", 0}, // 3562
+ {NULL, "", "", 0}, // 3564
+ {NULL, "", "", 0}, // 3565
#if wxUSE_GRAPHICS_CONTEXT
- {wxGCDC_new_0, "wxGCDC", "new", 0}, // 3563
+ {wxGCDC_new_0, "wxGCDC", "new", 0}, // 3566
#else
- {NULL, "wxGCDC", "new", 0}, // 3563
+ {NULL, "wxGCDC", "new", 0}, // 3566
#endif // wxUSE_GRAPHICS_CONTEXT
#if wxUSE_GRAPHICS_CONTEXT
- {NULL, "wxGCDC", "destroy", 1}, // 3564 obj destructor wxGCDC_destruct
+ {NULL, "wxGCDC", "destroy", 1}, // 3567 obj destructor wxGCDC_destruct
#else
- {NULL, "wxGCDC", "destroy", 0}, // 3564
+ {NULL, "wxGCDC", "destroy", 0}, // 3567
#endif // wxUSE_GRAPHICS_CONTEXT
#if wxUSE_GRAPHICS_CONTEXT
- {wxGCDC_GetGraphicsContext, "wxGCDC", "getGraphicsContext", 1}, // 3565
+ {wxGCDC_GetGraphicsContext, "wxGCDC", "getGraphicsContext", 1}, // 3568
#else
- {NULL, "wxGCDC", "getGraphicsContext", 0}, // 3565
+ {NULL, "wxGCDC", "getGraphicsContext", 0}, // 3568
#endif // wxUSE_GRAPHICS_CONTEXT
#if wxUSE_GRAPHICS_CONTEXT
- {wxGCDC_SetGraphicsContext, "wxGCDC", "setGraphicsContext", 2}, // 3566
+ {wxGCDC_SetGraphicsContext, "wxGCDC", "setGraphicsContext", 2}, // 3569
#else
- {NULL, "wxGCDC", "setGraphicsContext", 0}, // 3566
+ {NULL, "wxGCDC", "setGraphicsContext", 0}, // 3569
#endif // wxUSE_GRAPHICS_CONTEXT
- {wxNotificationMessage_new_0, "wxNotificationMessage", "new", 0}, // 3567
- {wxNotificationMessage_new_2, "wxNotificationMessage", "new", 2}, // 3568
- {NULL, "wxNotificationMessage", "destroy", 1}, // 3569 obj destructor wxNotificationMessage_destruct
+ {wxNotificationMessage_new_0, "wxNotificationMessage", "new", 0}, // 3570
+ {wxNotificationMessage_new_2, "wxNotificationMessage", "new", 2}, // 3571
+ {NULL, "wxNotificationMessage", "destroy", 1}, // 3572 obj destructor wxNotificationMessage_destruct
#if wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_AddAction, "wxNotificationMessage", "addAction", 3}, // 3570
+ {wxNotificationMessage_AddAction, "wxNotificationMessage", "addAction", 3}, // 3573
#else
- {NULL, "wxNotificationMessage", "addAction", 0}, // 3570
+ {NULL, "wxNotificationMessage", "addAction", 0}, // 3573
#endif // wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_Close, "wxNotificationMessage", "close", 1}, // 3571
- {wxNotificationMessage_SetFlags, "wxNotificationMessage", "setFlags", 2}, // 3572
+ {wxNotificationMessage_Close, "wxNotificationMessage", "close", 1}, // 3574
+ {wxNotificationMessage_SetFlags, "wxNotificationMessage", "setFlags", 2}, // 3575
#if wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_SetIcon, "wxNotificationMessage", "setIcon", 2}, // 3573
+ {wxNotificationMessage_SetIcon, "wxNotificationMessage", "setIcon", 2}, // 3576
#else
- {NULL, "wxNotificationMessage", "setIcon", 0}, // 3573
+ {NULL, "wxNotificationMessage", "setIcon", 0}, // 3576
#endif // wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_SetMessage, "wxNotificationMessage", "setMessage", 2}, // 3574
- {wxNotificationMessage_SetParent, "wxNotificationMessage", "setParent", 2}, // 3575
- {wxNotificationMessage_SetTitle, "wxNotificationMessage", "setTitle", 2}, // 3576
- {wxNotificationMessage_Show, "wxNotificationMessage", "show", 2}, // 3577
+ {wxNotificationMessage_SetMessage, "wxNotificationMessage", "setMessage", 2}, // 3577
+ {wxNotificationMessage_SetParent, "wxNotificationMessage", "setParent", 2}, // 3578
+ {wxNotificationMessage_SetTitle, "wxNotificationMessage", "setTitle", 2}, // 3579
+ {wxNotificationMessage_Show, "wxNotificationMessage", "show", 2}, // 3580
#if __WXMSW__
- {wxNotificationMessage_UseTaskBarIcon, "wxNotificationMessage", "useTaskBarIcon", 1}, // 3578
+ {wxNotificationMessage_UseTaskBarIcon, "wxNotificationMessage", "useTaskBarIcon", 1}, // 3581
#else
- {NULL, "wxNotificationMessage", "useTaskBarIcon", 0}, // 3578
+ {NULL, "wxNotificationMessage", "useTaskBarIcon", 0}, // 3581
#endif // __WXMSW__
#if __WXMSW__ && wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_MSWUseToasts, "wxNotificationMessage", "mSWUseToasts", 1}, // 3579
+ {wxNotificationMessage_MSWUseToasts, "wxNotificationMessage", "mSWUseToasts", 1}, // 3582
#else
- {NULL, "wxNotificationMessage", "mSWUseToasts", 0}, // 3579
+ {NULL, "wxNotificationMessage", "mSWUseToasts", 0}, // 3582
#endif // __WXMSW__ && wxCHECK_VERSION(3,1,0)
- {NULL, "", "", 0}, // 3580
+ {NULL, "", "", 0}, // 3583
#if WXE_WEBVIEW
- {wxWebView_New, "wxWebView", "new", 3}, // 3581
+ {wxWebView_New, "wxWebView", "new", 3}, // 3584
#else
- {NULL, "wxWebView", "new", 0}, // 3581
+ {NULL, "wxWebView", "new", 0}, // 3584
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetCurrentTitle, "wxWebView", "getCurrentTitle", 1}, // 3582
+ {wxWebView_GetCurrentTitle, "wxWebView", "getCurrentTitle", 1}, // 3585
#else
- {NULL, "wxWebView", "getCurrentTitle", 0}, // 3582
+ {NULL, "wxWebView", "getCurrentTitle", 0}, // 3585
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetCurrentURL, "wxWebView", "getCurrentURL", 1}, // 3583
+ {wxWebView_GetCurrentURL, "wxWebView", "getCurrentURL", 1}, // 3586
#else
- {NULL, "wxWebView", "getCurrentURL", 0}, // 3583
+ {NULL, "wxWebView", "getCurrentURL", 0}, // 3586
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetPageSource, "wxWebView", "getPageSource", 1}, // 3584
+ {wxWebView_GetPageSource, "wxWebView", "getPageSource", 1}, // 3587
#else
- {NULL, "wxWebView", "getPageSource", 0}, // 3584
+ {NULL, "wxWebView", "getPageSource", 0}, // 3587
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetPageText, "wxWebView", "getPageText", 1}, // 3585
+ {wxWebView_GetPageText, "wxWebView", "getPageText", 1}, // 3588
#else
- {NULL, "wxWebView", "getPageText", 0}, // 3585
+ {NULL, "wxWebView", "getPageText", 0}, // 3588
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_IsBusy, "wxWebView", "isBusy", 1}, // 3586
+ {wxWebView_IsBusy, "wxWebView", "isBusy", 1}, // 3589
#else
- {NULL, "wxWebView", "isBusy", 0}, // 3586
+ {NULL, "wxWebView", "isBusy", 0}, // 3589
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_IsEditable, "wxWebView", "isEditable", 1}, // 3587
+ {wxWebView_IsEditable, "wxWebView", "isEditable", 1}, // 3590
#else
- {NULL, "wxWebView", "isEditable", 0}, // 3587
+ {NULL, "wxWebView", "isEditable", 0}, // 3590
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_LoadURL, "wxWebView", "loadURL", 2}, // 3588
+ {wxWebView_LoadURL, "wxWebView", "loadURL", 2}, // 3591
#else
- {NULL, "wxWebView", "loadURL", 0}, // 3588
+ {NULL, "wxWebView", "loadURL", 0}, // 3591
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Print, "wxWebView", "print", 1}, // 3589
+ {wxWebView_Print, "wxWebView", "print", 1}, // 3592
#else
- {NULL, "wxWebView", "print", 0}, // 3589
+ {NULL, "wxWebView", "print", 0}, // 3592
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Reload, "wxWebView", "reload", 2}, // 3590
+ {wxWebView_Reload, "wxWebView", "reload", 2}, // 3593
#else
- {NULL, "wxWebView", "reload", 0}, // 3590
+ {NULL, "wxWebView", "reload", 0}, // 3593
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW && wxCHECK_VERSION(3,1,1)
- {wxWebView_RunScript, "wxWebView", "runScript", 2}, // 3591
+ {wxWebView_RunScript, "wxWebView", "runScript", 2}, // 3594
#else
- {NULL, "wxWebView", "runScript", 0}, // 3591
+ {NULL, "wxWebView", "runScript", 0}, // 3594
#endif // WXE_WEBVIEW && wxCHECK_VERSION(3,1,1)
#if WXE_WEBVIEW
- {wxWebView_SetEditable, "wxWebView", "setEditable", 2}, // 3592
+ {wxWebView_SetEditable, "wxWebView", "setEditable", 2}, // 3595
#else
- {NULL, "wxWebView", "setEditable", 0}, // 3592
+ {NULL, "wxWebView", "setEditable", 0}, // 3595
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_SetPage, "wxWebView", "setPage", 3}, // 3593
+ {wxWebView_SetPage, "wxWebView", "setPage", 3}, // 3596
#else
- {NULL, "wxWebView", "setPage", 0}, // 3593
+ {NULL, "wxWebView", "setPage", 0}, // 3596
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Stop, "wxWebView", "stop", 1}, // 3594
+ {wxWebView_Stop, "wxWebView", "stop", 1}, // 3597
#else
- {NULL, "wxWebView", "stop", 0}, // 3594
+ {NULL, "wxWebView", "stop", 0}, // 3597
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanCopy, "wxWebView", "canCopy", 1}, // 3595
+ {wxWebView_CanCopy, "wxWebView", "canCopy", 1}, // 3598
#else
- {NULL, "wxWebView", "canCopy", 0}, // 3595
+ {NULL, "wxWebView", "canCopy", 0}, // 3598
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanCut, "wxWebView", "canCut", 1}, // 3596
+ {wxWebView_CanCut, "wxWebView", "canCut", 1}, // 3599
#else
- {NULL, "wxWebView", "canCut", 0}, // 3596
+ {NULL, "wxWebView", "canCut", 0}, // 3599
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanPaste, "wxWebView", "canPaste", 1}, // 3597
+ {wxWebView_CanPaste, "wxWebView", "canPaste", 1}, // 3600
#else
- {NULL, "wxWebView", "canPaste", 0}, // 3597
+ {NULL, "wxWebView", "canPaste", 0}, // 3600
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Copy, "wxWebView", "copy", 1}, // 3598
+ {wxWebView_Copy, "wxWebView", "copy", 1}, // 3601
#else
- {NULL, "wxWebView", "copy", 0}, // 3598
+ {NULL, "wxWebView", "copy", 0}, // 3601
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Cut, "wxWebView", "cut", 1}, // 3599
+ {wxWebView_Cut, "wxWebView", "cut", 1}, // 3602
#else
- {NULL, "wxWebView", "cut", 0}, // 3599
+ {NULL, "wxWebView", "cut", 0}, // 3602
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Paste, "wxWebView", "paste", 1}, // 3600
+ {wxWebView_Paste, "wxWebView", "paste", 1}, // 3603
#else
- {NULL, "wxWebView", "paste", 0}, // 3600
+ {NULL, "wxWebView", "paste", 0}, // 3603
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_EnableContextMenu, "wxWebView", "enableContextMenu", 2}, // 3601
+ {wxWebView_EnableContextMenu, "wxWebView", "enableContextMenu", 2}, // 3604
#else
- {NULL, "wxWebView", "enableContextMenu", 0}, // 3601
+ {NULL, "wxWebView", "enableContextMenu", 0}, // 3604
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_IsContextMenuEnabled, "wxWebView", "isContextMenuEnabled", 1}, // 3602
+ {wxWebView_IsContextMenuEnabled, "wxWebView", "isContextMenuEnabled", 1}, // 3605
#else
- {NULL, "wxWebView", "isContextMenuEnabled", 0}, // 3602
+ {NULL, "wxWebView", "isContextMenuEnabled", 0}, // 3605
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanGoBack, "wxWebView", "canGoBack", 1}, // 3603
+ {wxWebView_CanGoBack, "wxWebView", "canGoBack", 1}, // 3606
#else
- {NULL, "wxWebView", "canGoBack", 0}, // 3603
+ {NULL, "wxWebView", "canGoBack", 0}, // 3606
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanGoForward, "wxWebView", "canGoForward", 1}, // 3604
+ {wxWebView_CanGoForward, "wxWebView", "canGoForward", 1}, // 3607
#else
- {NULL, "wxWebView", "canGoForward", 0}, // 3604
+ {NULL, "wxWebView", "canGoForward", 0}, // 3607
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_ClearHistory, "wxWebView", "clearHistory", 1}, // 3605
+ {wxWebView_ClearHistory, "wxWebView", "clearHistory", 1}, // 3608
#else
- {NULL, "wxWebView", "clearHistory", 0}, // 3605
+ {NULL, "wxWebView", "clearHistory", 0}, // 3608
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_EnableHistory, "wxWebView", "enableHistory", 2}, // 3606
+ {wxWebView_EnableHistory, "wxWebView", "enableHistory", 2}, // 3609
#else
- {NULL, "wxWebView", "enableHistory", 0}, // 3606
+ {NULL, "wxWebView", "enableHistory", 0}, // 3609
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GoBack, "wxWebView", "goBack", 1}, // 3607
+ {wxWebView_GoBack, "wxWebView", "goBack", 1}, // 3610
#else
- {NULL, "wxWebView", "goBack", 0}, // 3607
+ {NULL, "wxWebView", "goBack", 0}, // 3610
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GoForward, "wxWebView", "goForward", 1}, // 3608
+ {wxWebView_GoForward, "wxWebView", "goForward", 1}, // 3611
#else
- {NULL, "wxWebView", "goForward", 0}, // 3608
+ {NULL, "wxWebView", "goForward", 0}, // 3611
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_ClearSelection, "wxWebView", "clearSelection", 1}, // 3609
+ {wxWebView_ClearSelection, "wxWebView", "clearSelection", 1}, // 3612
#else
- {NULL, "wxWebView", "clearSelection", 0}, // 3609
+ {NULL, "wxWebView", "clearSelection", 0}, // 3612
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_DeleteSelection, "wxWebView", "deleteSelection", 1}, // 3610
+ {wxWebView_DeleteSelection, "wxWebView", "deleteSelection", 1}, // 3613
#else
- {NULL, "wxWebView", "deleteSelection", 0}, // 3610
+ {NULL, "wxWebView", "deleteSelection", 0}, // 3613
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetSelectedSource, "wxWebView", "getSelectedSource", 1}, // 3611
+ {wxWebView_GetSelectedSource, "wxWebView", "getSelectedSource", 1}, // 3614
#else
- {NULL, "wxWebView", "getSelectedSource", 0}, // 3611
+ {NULL, "wxWebView", "getSelectedSource", 0}, // 3614
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetSelectedText, "wxWebView", "getSelectedText", 1}, // 3612
+ {wxWebView_GetSelectedText, "wxWebView", "getSelectedText", 1}, // 3615
#else
- {NULL, "wxWebView", "getSelectedText", 0}, // 3612
+ {NULL, "wxWebView", "getSelectedText", 0}, // 3615
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_HasSelection, "wxWebView", "hasSelection", 1}, // 3613
+ {wxWebView_HasSelection, "wxWebView", "hasSelection", 1}, // 3616
#else
- {NULL, "wxWebView", "hasSelection", 0}, // 3613
+ {NULL, "wxWebView", "hasSelection", 0}, // 3616
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_SelectAll, "wxWebView", "selectAll", 1}, // 3614
+ {wxWebView_SelectAll, "wxWebView", "selectAll", 1}, // 3617
#else
- {NULL, "wxWebView", "selectAll", 0}, // 3614
+ {NULL, "wxWebView", "selectAll", 0}, // 3617
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanRedo, "wxWebView", "canRedo", 1}, // 3615
+ {wxWebView_CanRedo, "wxWebView", "canRedo", 1}, // 3618
#else
- {NULL, "wxWebView", "canRedo", 0}, // 3615
+ {NULL, "wxWebView", "canRedo", 0}, // 3618
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanUndo, "wxWebView", "canUndo", 1}, // 3616
+ {wxWebView_CanUndo, "wxWebView", "canUndo", 1}, // 3619
#else
- {NULL, "wxWebView", "canUndo", 0}, // 3616
+ {NULL, "wxWebView", "canUndo", 0}, // 3619
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Redo, "wxWebView", "redo", 1}, // 3617
+ {wxWebView_Redo, "wxWebView", "redo", 1}, // 3620
#else
- {NULL, "wxWebView", "redo", 0}, // 3617
+ {NULL, "wxWebView", "redo", 0}, // 3620
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Undo, "wxWebView", "undo", 1}, // 3618
+ {wxWebView_Undo, "wxWebView", "undo", 1}, // 3621
#else
- {NULL, "wxWebView", "undo", 0}, // 3618
+ {NULL, "wxWebView", "undo", 0}, // 3621
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Find, "wxWebView", "find", 3}, // 3619
+ {wxWebView_Find, "wxWebView", "find", 3}, // 3622
#else
- {NULL, "wxWebView", "find", 0}, // 3619
+ {NULL, "wxWebView", "find", 0}, // 3622
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanSetZoomType, "wxWebView", "canSetZoomType", 2}, // 3620
+ {wxWebView_CanSetZoomType, "wxWebView", "canSetZoomType", 2}, // 3623
#else
- {NULL, "wxWebView", "canSetZoomType", 0}, // 3620
+ {NULL, "wxWebView", "canSetZoomType", 0}, // 3623
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetZoom, "wxWebView", "getZoom", 1}, // 3621
+ {wxWebView_GetZoom, "wxWebView", "getZoom", 1}, // 3624
#else
- {NULL, "wxWebView", "getZoom", 0}, // 3621
+ {NULL, "wxWebView", "getZoom", 0}, // 3624
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetZoomType, "wxWebView", "getZoomType", 1}, // 3622
+ {wxWebView_GetZoomType, "wxWebView", "getZoomType", 1}, // 3625
#else
- {NULL, "wxWebView", "getZoomType", 0}, // 3622
+ {NULL, "wxWebView", "getZoomType", 0}, // 3625
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_SetZoom, "wxWebView", "setZoom", 2}, // 3623
+ {wxWebView_SetZoom, "wxWebView", "setZoom", 2}, // 3626
#else
- {NULL, "wxWebView", "setZoom", 0}, // 3623
+ {NULL, "wxWebView", "setZoom", 0}, // 3626
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_SetZoomType, "wxWebView", "setZoomType", 2}, // 3624
+ {wxWebView_SetZoomType, "wxWebView", "setZoomType", 2}, // 3627
#else
- {NULL, "wxWebView", "setZoomType", 0}, // 3624
+ {NULL, "wxWebView", "setZoomType", 0}, // 3627
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
- {wxWebView_GetZoomFactor, "wxWebView", "getZoomFactor", 1}, // 3625
+ {wxWebView_GetZoomFactor, "wxWebView", "getZoomFactor", 1}, // 3628
#else
- {NULL, "wxWebView", "getZoomFactor", 0}, // 3625
+ {NULL, "wxWebView", "getZoomFactor", 0}, // 3628
#endif // WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
#if WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
- {wxWebView_SetZoomFactor, "wxWebView", "setZoomFactor", 2}, // 3626
+ {wxWebView_SetZoomFactor, "wxWebView", "setZoomFactor", 2}, // 3629
#else
- {NULL, "wxWebView", "setZoomFactor", 0}, // 3626
+ {NULL, "wxWebView", "setZoomFactor", 0}, // 3629
#endif // WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
#if WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
- {wxWebView_IsBackendAvailable, "wxWebView", "isBackendAvailable", 1}, // 3627
+ {wxWebView_IsBackendAvailable, "wxWebView", "isBackendAvailable", 1}, // 3630
#else
- {NULL, "wxWebView", "isBackendAvailable", 0}, // 3627
+ {NULL, "wxWebView", "isBackendAvailable", 0}, // 3630
#endif // WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
#if WXE_WEBVIEW
- {wxWebViewEvent_GetString, "wxWebViewEvent", "getString", 1}, // 3628
+ {wxWebViewEvent_GetString, "wxWebViewEvent", "getString", 1}, // 3631
#else
- {NULL, "wxWebViewEvent", "getString", 0}, // 3628
+ {NULL, "wxWebViewEvent", "getString", 0}, // 3631
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebViewEvent_GetInt, "wxWebViewEvent", "getInt", 1}, // 3629
+ {wxWebViewEvent_GetInt, "wxWebViewEvent", "getInt", 1}, // 3632
#else
- {NULL, "wxWebViewEvent", "getInt", 0}, // 3629
+ {NULL, "wxWebViewEvent", "getInt", 0}, // 3632
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebViewEvent_GetTarget, "wxWebViewEvent", "getTarget", 1}, // 3630
+ {wxWebViewEvent_GetTarget, "wxWebViewEvent", "getTarget", 1}, // 3633
#else
- {NULL, "wxWebViewEvent", "getTarget", 0}, // 3630
+ {NULL, "wxWebViewEvent", "getTarget", 0}, // 3633
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebViewEvent_GetURL, "wxWebViewEvent", "getURL", 1}, // 3631
+ {wxWebViewEvent_GetURL, "wxWebViewEvent", "getURL", 1}, // 3634
#else
- {NULL, "wxWebViewEvent", "getURL", 0}, // 3631
+ {NULL, "wxWebViewEvent", "getURL", 0}, // 3634
#endif // WXE_WEBVIEW
};
diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp
index 4153f1e2b9..d29e8cb19a 100644
--- a/lib/wx/c_src/gen/wxe_init.cpp
+++ b/lib/wx/c_src/gen/wxe_init.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -5895,17 +5895,17 @@ void WxeApp::init_consts(wxeMetaCommand& event) {
#else
{ enif_make_atom(rt.env,"wxKeyCode"), "wxk_MEDIA_PLAY_PAUSE", WXE_ATOM_undefined },
#endif
-#if wxCHECK_VERSION(3,1,0)
+#if wxCHECK_VERSION(3,2,0)
{ enif_make_atom(rt.env,"wxKeyCode"), "wxk_LAUNCH_MAIL", rt.make_int(WXK_LAUNCH_MAIL) },
#else
{ enif_make_atom(rt.env,"wxKeyCode"), "wxk_LAUNCH_MAIL", WXE_ATOM_undefined },
#endif
-#if wxCHECK_VERSION(3,1,0)
+#if wxCHECK_VERSION(3,2,0)
{ enif_make_atom(rt.env,"wxKeyCode"), "wxk_LAUNCH_APP1", rt.make_int(WXK_LAUNCH_APP1) },
#else
{ enif_make_atom(rt.env,"wxKeyCode"), "wxk_LAUNCH_APP1", WXE_ATOM_undefined },
#endif
-#if wxCHECK_VERSION(3,1,0)
+#if wxCHECK_VERSION(3,2,0)
{ enif_make_atom(rt.env,"wxKeyCode"), "wxk_LAUNCH_APP2", rt.make_int(WXK_LAUNCH_APP2) },
#else
{ enif_make_atom(rt.env,"wxKeyCode"), "wxk_LAUNCH_APP2", WXE_ATOM_undefined },
diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h
index d8e8a0f7ea..0d514a1709 100644
--- a/lib/wx/c_src/gen/wxe_macros.h
+++ b/lib/wx/c_src/gen/wxe_macros.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,6 +73,9 @@
#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE
#include <wx/msw/webview_ie.h>
#endif
+#if wxUSE_GLCANVAS_EGL && !wxCHECK_VERSION(3,2,3)
+#include <EGL/egl.h>
+#endif
#ifndef wxICON_DEFAULT_BITMAP_TYPE
diff --git a/lib/wx/c_src/gen/wxe_wrapper_3.cpp b/lib/wx/c_src/gen/wxe_wrapper_3.cpp
index e2e063fd31..4f6fe807a5 100644
--- a/lib/wx/c_src/gen/wxe_wrapper_3.cpp
+++ b/lib/wx/c_src/gen/wxe_wrapper_3.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -2620,6 +2620,51 @@ void wxGLCanvas_SetCurrent(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
}
+#if wxUSE_GLCANVAS_EGL
+// wxGLCanvas::CreateSurface
+void wxGLCanvas_CreateSurface(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxGLCanvas *This;
+ This = (wxGLCanvas *) memenv->getPtr(env, argv[0], "This");
+
+#if !wxCHECK_VERSION(3,2,3)
+ if(!This) throw wxe_badarg(0);
+ if(This->GetEGLSurface() != EGL_NO_SURFACE)
+ eglDestroySurface(This->GetEGLDisplay(), This->GetEGLSurface());
+#endif
+;
+ if(!This) throw wxe_badarg("This");
+ bool Result = This->CreateSurface();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
+#endif
+// wxGLCanvas::IsDisplaySupported
+void wxGLCanvas_IsDisplaySupported(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ int attribList_tmp;
+ unsigned int attribListLen;
+ ERL_NIF_TERM attribListHead, attribListTail;
+ if(!enif_get_list_length(env, argv[0], &attribListLen)) Badarg("attribList");
+ std::vector <int> attribList;
+ attribListTail = argv[0];
+ while(!enif_is_empty_list(env, attribListTail)) {
+ if(!enif_get_list_cell(env, attribListTail, &attribListHead, &attribListTail)) Badarg("attribList");
+ if(!enif_get_int(env, attribListHead, &attribList_tmp)) Badarg("attribList");
+ attribList.push_back( (int) attribList_tmp);
+ };
+ bool Result = wxGLCanvas::IsDisplaySupported(attribList.data());
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
// wxGLCanvas::SwapBuffers
void wxGLCanvas_SwapBuffers(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
{
@@ -2680,6 +2725,22 @@ void wxGLContext_SetCurrent(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
}
+#if wxCHECK_VERSION(3,1,0)
+// wxGLContext::IsOK
+void wxGLContext_IsOK(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxGLContext *This;
+ This = (wxGLContext *) memenv->getPtr(env, argv[0], "This");
+ if(!This) throw wxe_badarg("This");
+ bool Result = This->IsOK();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
+#endif
#endif // wxUSE_GLCANVAS
// wxGauge::wxGauge
void wxGauge_new_0(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
diff --git a/lib/wx/c_src/wxe_gl.cpp b/lib/wx/c_src/wxe_gl.cpp
index 46c4cc7679..e2327cfb54 100644
--- a/lib/wx/c_src/wxe_gl.cpp
+++ b/lib/wx/c_src/wxe_gl.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,16 +44,25 @@ int egl_initiated = 0;
wxeGLC glc;
typedef void * (*WXE_GL_LOOKUP) (int);
-WXE_GL_LOOKUP wxe_gl_lookup_func = NULL;
+void * wxe_not_loaded(int x);
+WXE_GL_LOOKUP wxe_gl_lookup_func = (WXE_GL_LOOKUP) wxe_not_loaded;
typedef void * (*WXE_GL_FUNC) (ErlNifEnv*, ErlNifPid*, const ERL_NIF_TERM argv[]);
+typedef const char * (*WXE_GL_FUNC_NAME) (int);
+WXE_GL_FUNC_NAME wxe_gl_lookup_func_name;
+
extern "C" {
-void wxe_initOpenGL(void * fptr) {
+void wxe_initOpenGL(void * fptr, void *name_fptr) {
wxe_gl_lookup_func = (WXE_GL_LOOKUP) fptr;
+ wxe_gl_lookup_func_name = (WXE_GL_FUNC_NAME) name_fptr;
enif_set_pid_undefined(&gl_active_pid);
}
}
+void * wxe_not_loaded(int x) {
+ return NULL;
+}
+
ErlNifUInt64 wxe_make_hash(ErlNifEnv *env, ErlNifPid *pid)
{
ERL_NIF_TERM term = enif_make_pid(env, pid);
@@ -113,9 +122,23 @@ void no_context(wxeCommand *event) {
enif_clear_env(event->env);
}
-void gl_dispatch(wxeCommand *event) {
+void gl_print_cmd(wxeCommand *event)
+{
+ int i;
+ const char *func = wxe_gl_lookup_func_name(event->op);
+ enif_fprintf(stderr, " %T %d %s(", event->caller, event->op, func);
+ for(i=0; i < event->argc; i++) {
+ wx_print_term(event->env, event->args[i]);
+ if(i < event->argc - 1)
+ enif_fprintf(stderr, ", ");
+ }
+ enif_fprintf(stderr, ")\r\n");
+}
+
+void gl_dispatch(wxeCommand *event)
+{
WXE_GL_FUNC fptr;
- if(egl_initiated) {
+ if((fptr = (WXE_GL_FUNC) wxe_gl_lookup_func(event->op))) {
if(enif_compare_pids(&(event->caller),&gl_active_pid) != 0) {
ErlNifUInt64 caller_index = wxe_make_hash(event->env, &(event->caller));
wxe_glc * current = glc[caller_index];
@@ -131,12 +154,10 @@ void gl_dispatch(wxeCommand *event) {
return;
}
}
- } else {
- no_context(event);
- return;
- }
- if((fptr = (WXE_GL_FUNC) wxe_gl_lookup_func(event->op))) {
// enif_fprintf(stderr, "GL: caller %T gl_active %T %d\r\n", event->caller, gl_active_pid, event->op);
+ if(wxe_debug) {
+ gl_print_cmd(event);
+ }
fptr(event->env, &event->caller, event->args);
} else {
enif_send(NULL, &event->caller, event->env,
diff --git a/lib/wx/c_src/wxe_gl.h b/lib/wx/c_src/wxe_gl.h
index 6c57e1b645..12aea9bb8c 100644
--- a/lib/wx/c_src/wxe_gl.h
+++ b/lib/wx/c_src/wxe_gl.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ void setActiveGL(wxeMemEnv *memenv, ErlNifPid caller, wxGLCanvas *canvas, wxGLCo
void deleteActiveGL(wxGLCanvas *canvas);
void gl_dispatch(wxeCommand *);
extern "C" {
- void wxe_initOpenGL(void * fptr);
+ void wxe_initOpenGL(void * fptr, void *name_fptr);
}
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index a32e09db01..5ea1371524 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,27 +113,46 @@ void meta_command(ErlNifEnv *env, int what, wxe_me_ref *mp) {
void send_msg(const char * type, const wxString * msg) {
WxeApp * app = (WxeApp *) wxTheApp;
wxeReturn rt = wxeReturn(app->global_me, init_caller);
+ ErlNifEnv *env = enif_alloc_env();
+ rt.env = env;
ERL_NIF_TERM emsg = enif_make_tuple3(rt.env,
rt.make_atom((char *) "wxe_driver"),
rt.make_atom((char *) type),
rt.make(msg));
rt.send(emsg);
+ enif_free_env(env);
}
+void wx_print_term(ErlNifEnv * env, ERL_NIF_TERM t)
+{
+ if(enif_is_binary(env, t)) {
+ ErlNifBinary bin;
+ enif_inspect_binary(env, t, &bin);
+ if(bin.size > 128) {
+ enif_fprintf(stderr, "<<...LARGE BIN>");
+ } else {
+ enif_fprintf(stderr, "%T", t);
+ }
+ } else {
+ enif_fprintf(stderr, "%T", t);
+ }
+}
+
+
+
void print_cmd(wxeCommand& event)
{
int i;
wxe_fns_t *func = &wxe_fns[event.op];
enif_fprintf(stderr, " %T %d %s::%s(", event.caller, event.op, func->cname, func->fname);
- for(i=0; i < event.argc-1; i++) {
- enif_fprintf(stderr, "%T,", event.args[i]);
- }
- if(i > 0) {
- enif_fprintf(stderr, "%T)\r\n", event.args[i]);
- } else {
- enif_fprintf(stderr, ")\r\n");
+ for(i=0; i < event.argc; i++) {
+ wx_print_term(event.env, event.args[i]);
+ if(i < event.argc - 1)
+ enif_fprintf(stderr, ", ");
}
+ enif_fprintf(stderr, ")\r\n");
}
+
/* ************************************************************
* Init WxeApp the application emulator
diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h
index ee8654d1ef..a99c30a254 100644
--- a/lib/wx/c_src/wxe_impl.h
+++ b/lib/wx/c_src/wxe_impl.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -115,4 +115,7 @@ typedef struct {
extern wxe_fns_t wxe_fns[];
+void wx_print_term(ErlNifEnv * env, ERL_NIF_TERM t);
+
+
#endif //_WXE_IMPL_H
diff --git a/lib/wx/c_src/wxe_nif.c b/lib/wx/c_src/wxe_nif.c
index 6f6251e482..a7d3fea885 100644
--- a/lib/wx/c_src/wxe_nif.c
+++ b/lib/wx/c_src/wxe_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2017-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2017-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@ ERL_NIF_TERM WXE_ATOM_wxPrintDialogData;
ErlNifResourceType* wxeMemEnvRt = NULL;
int wxe_debug = 0;
-extern void wxe_initOpenGL(void * fptr);
+extern void wxe_initOpenGL(void * fptr, void *debug);
// void destroyMemEnv(wxeMemEnv *memenv);
@@ -127,9 +127,13 @@ static ERL_NIF_TERM wx_setup_cmd(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
static ERL_NIF_TERM wx_init_opengl(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
void * fptr;
+ void * debug;
if(!get_ptr(env, argv[0], &fptr))
return enif_make_badarg(env);
- wxe_initOpenGL(fptr);
+ if(!get_ptr(env, argv[1], &debug))
+ return enif_make_badarg(env);
+
+ wxe_initOpenGL(fptr, debug);
return WXE_ATOM_ok;
}
@@ -198,7 +202,7 @@ static ErlNifFunc nif_funcs[] =
{"queue_cmd",13, wx_setup_cmd},
{"queue_cmd",14, wx_setup_cmd},
{"queue_cmd",15, wx_setup_cmd},
- {"init_opengl", 1, wx_init_opengl},
+ {"init_opengl", 2, wx_init_opengl},
{"make_env", 0, wxe_make_env},
{"delete_env", 1, wxe_delete_env},
{"debug_driver", 1, wxe_debug_driver},
diff --git a/lib/wx/c_src/wxe_return.cpp b/lib/wx/c_src/wxe_return.cpp
index 7d2e072561..8728dafcf9 100644
--- a/lib/wx/c_src/wxe_return.cpp
+++ b/lib/wx/c_src/wxe_return.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,8 +43,11 @@ wxeReturn::~wxeReturn () {
int wxeReturn::send(ERL_NIF_TERM msg) {
int res;
if(wxe_debug) {
- if(isResult)
- enif_fprintf(stderr, "return to %T: %T\r\n", caller, msg);
+ if(isResult) {
+ enif_fprintf(stderr, "return to %T: ", caller);
+ wx_print_term(env, msg);
+ enif_fprintf(stderr, "\r\n");
+ }
}
if(isResult) {
res = enif_send(NULL, &caller, env,
diff --git a/lib/wx/configure.ac b/lib/wx/configure.ac
index 71eaa98786..6b73ddc205 100644
--- a/lib/wx/configure.ac
+++ b/lib/wx/configure.ac
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. -*-m4-*-
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 2008-2022. All Rights Reserved.
+dnl Copyright Ericsson AB 2008-2023. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
diff --git a/lib/wx/doc/src/gl.xml b/lib/wx/doc/src/gl.xml
index 224c9d90f3..1f35f8fa89 100644
--- a/lib/wx/doc/src/gl.xml
+++ b/lib/wx/doc/src/gl.xml
@@ -7,7 +7,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2021</year>
+ <year>2020</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder></copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
@@ -928,10 +928,10 @@
<p><url href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDebugMessageControl.xhtml">External documentation.</url></p></desc>
</func>
<func>
- <name name="debugMessageInsert" arity="6" clause_i="1" since=""/>
+ <name name="debugMessageInsert" arity="5" clause_i="1" since=""/>
<fsummary>inject an application-supplied message into the debug message queue</fsummary>
<desc>
- <p><seemfa marker="gl#debugMessageInsert/6"><c>gl:debugMessageInsert/6</c></seemfa> inserts a user-supplied message into the debug output queue. <c>Source</c> specifies the source that will be used to classify the message and must be <c>?GL_DEBUG_SOURCE_APPLICATION</c> or <c>?GL_DEBUG_SOURCE_THIRD_PARTY</c>. All other sources are reserved for use by the GL implementation. <c>Type</c> indicates the type of the message to be inserted and may be one of <c>?GL_DEBUG_TYPE_ERROR</c>, <c>?GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR</c>, <c>?GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR</c>, <c>?GL_DEBUG_TYPE_PORTABILITY</c>, <c>?GL_DEBUG_TYPE_PERFORMANCE</c>, <c>?GL_DEBUG_TYPE_MARKER</c>, <c>?GL_DEBUG_TYPE_PUSH_GROUP</c>, <c>?GL_DEBUG_TYPE_POP_GROUP</c>, or <c>?GL_DEBUG_TYPE_OTHER</c>. <c>Severity</c> indicates the severity of the message and may be <c>?GL_DEBUG_SEVERITY_LOW</c>, <c>?GL_DEBUG_SEVERITY_MEDIUM</c>, <c>?GL_DEBUG_SEVERITY_HIGH</c> or <c>?GL_DEBUG_SEVERITY_NOTIFICATION</c>. <c>Id</c> is available for application defined use and may be any value. This value will be recorded and used to identify the message. </p>
+ <p><seemfa marker="gl#debugMessageInsert/5"><c>gl:debugMessageInsert/5</c></seemfa> inserts a user-supplied message into the debug output queue. <c>Source</c> specifies the source that will be used to classify the message and must be <c>?GL_DEBUG_SOURCE_APPLICATION</c> or <c>?GL_DEBUG_SOURCE_THIRD_PARTY</c>. All other sources are reserved for use by the GL implementation. <c>Type</c> indicates the type of the message to be inserted and may be one of <c>?GL_DEBUG_TYPE_ERROR</c>, <c>?GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR</c>, <c>?GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR</c>, <c>?GL_DEBUG_TYPE_PORTABILITY</c>, <c>?GL_DEBUG_TYPE_PERFORMANCE</c>, <c>?GL_DEBUG_TYPE_MARKER</c>, <c>?GL_DEBUG_TYPE_PUSH_GROUP</c>, <c>?GL_DEBUG_TYPE_POP_GROUP</c>, or <c>?GL_DEBUG_TYPE_OTHER</c>. <c>Severity</c> indicates the severity of the message and may be <c>?GL_DEBUG_SEVERITY_LOW</c>, <c>?GL_DEBUG_SEVERITY_MEDIUM</c>, <c>?GL_DEBUG_SEVERITY_HIGH</c> or <c>?GL_DEBUG_SEVERITY_NOTIFICATION</c>. <c>Id</c> is available for application defined use and may be any value. This value will be recorded and used to identify the message. </p>
<p><url href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDebugMessageInsert.xhtml">External documentation.</url></p></desc>
</func>
@@ -1798,11 +1798,8 @@
<func>
<name name="getInternalformati64v" arity="4" clause_i="1" since=""/>
<name name="getInternalformativ" arity="4" clause_i="1" since=""/>
- <fsummary>retrieve information about implementation-dependent support for internal formats</fsummary>
- <desc>
- <p><seemfa marker="gl#getInternalformativ/4"><c>gl:getInternalformativ/4</c></seemfa> and <seemfa marker="gl#getInternalformativ/4"><c>gl:getInternalformati64v/4</c></seemfa> retrieve information about implementation-dependent support for internal formats. <c>Target</c> indicates the target with which the internal format will be used and must be one of <c>?GL_RENDERBUFFER</c>, <c>?GL_TEXTURE_2D_MULTISAMPLE</c>, or <c>?GL_TEXTURE_2D_MULTISAMPLE_ARRAY</c>, corresponding to usage as a renderbuffer, two-dimensional multisample texture or two-dimensional multisample array texture, respectively. </p>
-
- <p><url href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetInternalFormat.xhtml">External documentation.</url></p></desc>
+ <fsummary/>
+ <desc><p>No documentation available.</p></desc>
</func>
<func>
<name name="getLightfv" arity="2" clause_i="1" since=""/>
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index f155b7a551..08e339e097 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -32,6 +32,22 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 2.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improve debug prints from the nifs. Some minor fixes for
+ wxWidgets-3.2. Fixed OpenGL debug functions.</p>
+ <p>
+ Own Id: OTP-18512</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 2.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/wx/doc/src/wxGLCanvas.xml b/lib/wx/doc/src/wxGLCanvas.xml
index 2ccfb6e137..00c10cd1f1 100644
--- a/lib/wx/doc/src/wxGLCanvas.xml
+++ b/lib/wx/doc/src/wxGLCanvas.xml
@@ -7,7 +7,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2021</year>
+ <year>2020</year><year>2023</year>
<holder>wxWidgets team.</holder></copyright>
<legalnotice>Licensed under the wxWindows Free Documentation Licence, Version 3
</legalnotice>
@@ -57,6 +57,21 @@
</func>
<func>
+ <name name="createSurface" arity="1" clause_i="1" since=""/>
+ <fsummary/>
+ <desc/>
+ </func>
+
+ <func>
+ <name name="isDisplaySupported" arity="1" clause_i="1" since=""/>
+ <fsummary>Determines if a canvas having the specified attributes is available. </fsummary>
+ <desc><p>Determines if a canvas having the specified attributes is available.
+ </p><p>This only applies for visual attributes, not rendering context attributes. Please, use the new form of this method, using <c>wxGLAttributes</c> (not implemented in wx).
+ </p><p>Return: true if attributes are supported.
+ </p></desc>
+ </func>
+
+ <func>
<name name="swapBuffers" arity="1" clause_i="1" since=""/>
<fsummary>Swaps the double-buffer of this window, making the back-buffer the front-buffer and vice versa, so that the output of the previous OpenGL commands is displayed on the window. </fsummary>
<desc><p>Swaps the double-buffer of this window, making the back-buffer the front-buffer and vice versa, so that the output of the previous OpenGL commands is displayed on the window.
diff --git a/lib/wx/doc/src/wxGLContext.xml b/lib/wx/doc/src/wxGLContext.xml
index 60214ff35b..8aa99999f8 100644
--- a/lib/wx/doc/src/wxGLContext.xml
+++ b/lib/wx/doc/src/wxGLContext.xml
@@ -7,7 +7,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2021</year>
+ <year>2020</year><year>2023</year>
<holder>wxWidgets team.</holder></copyright>
<legalnotice>Licensed under the wxWindows Free Documentation Licence, Version 3
</legalnotice>
@@ -21,7 +21,7 @@
</p><p>Binding (making current) a rendering context with another instance of a <seeerl marker="wxGLCanvas"><c>wxGLCanvas</c></seeerl> however works only if the both <seeerl marker="wxGLCanvas"><c>wxGLCanvas</c></seeerl> instances were created with the same attributes.
</p><p>OpenGL version 3 introduced a new type of specification profile, the modern core profile. The old compatibility profile maintains all legacy features. Since wxWidgets 3.1.0 you can choose the type of context and even ask for a specified OGL version number. However, its advised to use only core profile as the compatibility profile may run a bit slower.
</p><p>OpenGL core profile specification defines several flags at context creation that determine not only the type of context but also some features. Some of these flags can be set in the list of attributes used at <seeerl marker="wxGLCanvas"><c>wxGLCanvas</c></seeerl> ctor. But since wxWidgets 3.1.0 it is strongly encouraged to use the new mechanism: setting the context attributes with a <c>wxGLContextAttrs</c> (not implemented in wx) object and the canvas attributes with a <c>wxGLAttributes</c> (not implemented in wx) object.
- </p><p>The best way of knowing if your OpenGL environment supports a specific type of context is creating a <seeerl marker="wxGLContext"><c>wxGLContext</c></seeerl> instance and checking <c>wxGLContext::IsOK()</c> (not implemented in wx). If it returns false, then simply delete that instance and create a new one with other attributes.
+ </p><p>The best way of knowing if your OpenGL environment supports a specific type of context is creating a <seeerl marker="wxGLContext"><c>wxGLContext</c></seeerl> instance and checking <seemfa marker="#isOK/1"><c>isOK/1</c></seemfa>. If it returns false, then simply delete that instance and create a new one with other attributes.
</p><p>wxHAS_OPENGL_ES is defined on platforms that only have this implementation available (e.g. the iPhone) and don't support the full specification.
</p><p>See: <seeerl marker="wxGLCanvas"><c>wxGLCanvas</c></seeerl>, <c>wxGLContextAttrs</c> (not implemented in wx), <c>wxGLAttributes</c> (not implemented in wx)
</p>
@@ -51,6 +51,15 @@
</func>
<func>
+ <name name="isOK" arity="1" clause_i="1" since=""/>
+ <fsummary>Checks if the underlying OpenGL rendering context was correctly created by the system with the requested attributes. </fsummary>
+ <desc><p>Checks if the underlying OpenGL rendering context was correctly created by the system with the requested attributes.
+ </p><p>If this function returns false then the <seeerl marker="wxGLContext"><c>wxGLContext</c></seeerl> object is useless and should be deleted and recreated with different attributes.
+ </p><p>Since: 3.1.0
+ </p></desc>
+ </func>
+
+ <func>
<name name="destroy" arity="1" clause_i="1" since=""/>
<fsummary>Destructor</fsummary>
<desc><p>Destroys the object.</p></desc>
diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl
index 38ba71c5f7..1b61fb4390 100644
--- a/lib/wx/include/wx.hrl
+++ b/lib/wx/include/wx.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -903,7 +903,7 @@
-define(wxDF_LOCALE, 16).
-define(wxDF_PRIVATE, 20).
-define(wxDF_HTML, 30).
--define(wxDF_MAX, 31).
+-define(wxDF_MAX, wxe_util:get_const(wxDF_MAX)).
%%% From "defs.h": wxDeprecatedGUIConstants
-define(wxDEFAULT, 70).
-define(wxDECORATIVE, 71).
diff --git a/lib/wx/src/gen/gl.erl b/lib/wx/src/gen/gl.erl
index d1c6e76937..283af4a869 100644
--- a/lib/wx/src/gen/gl.erl
+++ b/lib/wx/src/gen/gl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -238,7 +238,7 @@
texStorage2DMultisample/6,texStorage3DMultisample/7,textureView/8,
bindVertexBuffer/4,vertexAttribFormat/5,vertexAttribIFormat/4,vertexAttribLFormat/4,
vertexAttribBinding/2,vertexBindingDivisor/2,debugMessageControl/5,
- debugMessageInsert/6,getDebugMessageLog/2,pushDebugGroup/4,popDebugGroup/0,
+ debugMessageInsert/5,getDebugMessageLog/2,pushDebugGroup/4,popDebugGroup/0,
objectPtrLabel/3,bufferStorage/4,clearTexImage/5,clearTexSubImage/11,
bindBuffersBase/3,bindBuffersRange/5,bindTextures/2,bindSamplers/2,
bindImageTextures/2,bindVertexBuffers/4,clipControl/2,createTransformFeedbacks/1,
@@ -299,8 +299,8 @@
bindAttribLocationARB/3,getActiveAttribARB/3,getAttribLocationARB/2,
blendBarrierKHR/0,maxShaderCompilerThreadsKHR/1,depthBoundsEXT/2]).
--export([get_interface/0, rec/1, lookup_func/0]).
--nifs([lookup_func/0]).
+-export([get_interface/0, rec/1, lookup_func/1]).
+-nifs([lookup_func_nif/1]).
-define(nif_stub,nif_stub_error(?LINE)).
%% @hidden
nif_stub_error(Line) ->
@@ -332,7 +332,10 @@ rec(Op) ->
rec(Op)
end.
-lookup_func() -> ?nif_stub.
+lookup_func(functions) -> lookup_func_nif(1);
+lookup_func(function_names) -> lookup_func_nif(2).
+
+lookup_func_nif(_Func) -> ?nif_stub.
@@ -5116,15 +5119,14 @@ debugMessageControl(Source,Type,Severity,Ids,Enabled) when is_integer(Source),is
IF:queue_cmd(Source,Type,Severity,Count,Ids,Enabled,5802),
ok.
--spec debugMessageInsert(Source, Type, Id, Severity, Length, Buf) -> 'ok'
- when Source::enum(), Type::enum(), Id::i(), Severity::enum(), Length::i(), Buf::string().
-debugMessageInsert(Source,Type,Id,Severity,Length,Buf) when is_integer(Source),is_integer(Type),is_integer(Id),is_integer(Severity),is_integer(Length),is_list(Buf) ->
+-spec debugMessageInsert(Source::enum(), Type::enum(), Id::i(), Severity::enum(), Buf::string()) -> 'ok'.
+debugMessageInsert(Source,Type,Id,Severity,Buf) when is_integer(Source),is_integer(Type),is_integer(Id),is_integer(Severity),is_list(Buf) ->
IF = get_interface(),
BufBin = unicode:characters_to_binary([Buf|[0]]),
- IF:queue_cmd(Source,Type,Id,Severity,Length,BufBin,5803),
+ IF:queue_cmd(Source,Type,Id,Severity,BufBin,5803),
ok.
--spec getDebugMessageLog(Count::i(), BufSize::i()) -> {i(),Sources::[enum()],Types::[enum()],Ids::[i()],Severities::[enum()],MessageLog::string()}.
+-spec getDebugMessageLog(Count::i(), BufSize::i()) -> {i(),Sources::[enum()],Types::[enum()],Ids::[i()],Severities::[enum()],MessageLog::[string()]}.
getDebugMessageLog(Count,BufSize) when is_integer(Count),is_integer(BufSize) ->
IF = get_interface(),
IF:queue_cmd(Count,BufSize,5804),
diff --git a/lib/wx/src/gen/wxGLCanvas.erl b/lib/wx/src/gen/wxGLCanvas.erl
index 29a54f527d..3a6cc682be 100644
--- a/lib/wx/src/gen/wxGLCanvas.erl
+++ b/lib/wx/src/gen/wxGLCanvas.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,8 @@
-module(wxGLCanvas).
-include("wxe.hrl").
--export([destroy/1,new/1,new/2,setCurrent/2,swapBuffers/1]).
+-export([createSurface/1,destroy/1,isDisplaySupported/1,new/1,new/2,setCurrent/2,
+ swapBuffers/1]).
%% inherited exports
-export([cacheBestSize/2,canSetTransparent/1,captureMouse/1,center/1,center/2,
@@ -112,6 +113,22 @@ setCurrent(#wx_ref{type=ThisT}=This,#wx_ref{type=ContextT}=Context) ->
wxe_util:queue_cmd(This,Context,?get_env(),?wxGLCanvas_SetCurrent),
wxe_util:rec(?wxGLCanvas_SetCurrent).
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxglcanvas.html#wxglcanvascreatesurface">external documentation</a>.
+-spec createSurface(This) -> boolean() when
+ This::wxGLCanvas().
+createSurface(#wx_ref{type=ThisT}=This) ->
+ ?CLASS(ThisT,wxGLCanvas),
+ wxe_util:queue_cmd(This,?get_env(),?wxGLCanvas_CreateSurface),
+ wxe_util:rec(?wxGLCanvas_CreateSurface).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxglcanvas.html#wxglcanvasisdisplaysupported">external documentation</a>.
+-spec isDisplaySupported(AttribList) -> boolean() when
+ AttribList::[integer()].
+isDisplaySupported(AttribList)
+ when is_list(AttribList) ->
+ wxe_util:queue_cmd(AttribList,?get_env(),?wxGLCanvas_IsDisplaySupported),
+ wxe_util:rec(?wxGLCanvas_IsDisplaySupported).
+
%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxglcanvas.html#wxglcanvasswapbuffers">external documentation</a>.
-spec swapBuffers(This) -> boolean() when
This::wxGLCanvas().
diff --git a/lib/wx/src/gen/wxGLContext.erl b/lib/wx/src/gen/wxGLContext.erl
index 2308c658ef..00016ee6b6 100644
--- a/lib/wx/src/gen/wxGLContext.erl
+++ b/lib/wx/src/gen/wxGLContext.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
-module(wxGLContext).
-include("wxe.hrl").
--export([destroy/1,new/1,new/2,setCurrent/2]).
+-export([destroy/1,isOK/1,new/1,new/2,setCurrent/2]).
%% inherited exports
-export([parent_class/1]).
@@ -60,6 +60,14 @@ setCurrent(#wx_ref{type=ThisT}=This,#wx_ref{type=WinT}=Win) ->
wxe_util:queue_cmd(This,Win,?get_env(),?wxGLContext_SetCurrent),
wxe_util:rec(?wxGLContext_SetCurrent).
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxglcontext.html#wxglcontextisok">external documentation</a>.
+-spec isOK(This) -> boolean() when
+ This::wxGLContext().
+isOK(#wx_ref{type=ThisT}=This) ->
+ ?CLASS(ThisT,wxGLContext),
+ wxe_util:queue_cmd(This,?get_env(),?wxGLContext_IsOK),
+ wxe_util:rec(?wxGLContext_IsOK).
+
%% @doc Destroys this object, do not use object again
-spec destroy(This::wxGLContext()) -> 'ok'.
destroy(Obj=#wx_ref{type=Type}) ->
diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl
index e20f2699f7..86b9114b09 100644
--- a/lib/wx/src/gen/wxe_funcs.hrl
+++ b/lib/wx/src/gen/wxe_funcs.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -2322,1135 +2322,1138 @@
-define(wxHtmlEasyPrinting_destroy, 2492).
-define(wxGLCanvas_new, 2493).
-define(wxGLCanvas_SetCurrent, 2494).
--define(wxGLCanvas_SwapBuffers, 2495).
--define(wxGLCanvas_destroy, 2496).
--define(wxGLContext_new, 2497).
--define(wxGLContext_SetCurrent, 2498).
--define(wxGLContext_destroy, 2499).
--define(wxAuiManager_new, 2500).
--define(wxAuiManager_destruct, 2501).
--define(wxAuiManager_AddPane_2_1, 2502).
--define(wxAuiManager_AddPane_2_0, 2503).
--define(wxAuiManager_AddPane_3, 2504).
--define(wxAuiManager_DetachPane, 2505).
--define(wxAuiManager_GetAllPanes, 2506).
--define(wxAuiManager_GetArtProvider, 2507).
--define(wxAuiManager_GetDockSizeConstraint, 2508).
--define(wxAuiManager_GetFlags, 2509).
--define(wxAuiManager_GetManagedWindow, 2510).
--define(wxAuiManager_GetManager, 2511).
--define(wxAuiManager_GetPane_1_1, 2512).
--define(wxAuiManager_GetPane_1_0, 2513).
--define(wxAuiManager_HideHint, 2514).
--define(wxAuiManager_InsertPane, 2515).
--define(wxAuiManager_LoadPaneInfo, 2516).
--define(wxAuiManager_LoadPerspective, 2517).
--define(wxAuiManager_SavePaneInfo, 2518).
--define(wxAuiManager_SavePerspective, 2519).
--define(wxAuiManager_SetArtProvider, 2520).
--define(wxAuiManager_SetDockSizeConstraint, 2521).
--define(wxAuiManager_SetFlags, 2522).
--define(wxAuiManager_SetManagedWindow, 2523).
--define(wxAuiManager_ShowHint, 2524).
--define(wxAuiManager_UnInit, 2525).
--define(wxAuiManager_Update, 2526).
--define(wxAuiPaneInfo_new_0, 2527).
--define(wxAuiPaneInfo_new_1, 2528).
--define(wxAuiPaneInfo_BestSize_1, 2529).
--define(wxAuiPaneInfo_BestSize_2, 2530).
--define(wxAuiPaneInfo_Bottom, 2531).
--define(wxAuiPaneInfo_BottomDockable, 2532).
--define(wxAuiPaneInfo_Caption, 2533).
--define(wxAuiPaneInfo_CaptionVisible, 2534).
--define(wxAuiPaneInfo_Centre, 2535).
--define(wxAuiPaneInfo_CentrePane, 2536).
--define(wxAuiPaneInfo_CloseButton, 2537).
--define(wxAuiPaneInfo_DefaultPane, 2538).
--define(wxAuiPaneInfo_DestroyOnClose, 2539).
--define(wxAuiPaneInfo_Direction, 2540).
--define(wxAuiPaneInfo_Dock, 2541).
--define(wxAuiPaneInfo_Dockable, 2542).
--define(wxAuiPaneInfo_Fixed, 2543).
--define(wxAuiPaneInfo_Float, 2544).
--define(wxAuiPaneInfo_Floatable, 2545).
--define(wxAuiPaneInfo_FloatingPosition_1, 2546).
--define(wxAuiPaneInfo_FloatingPosition_2, 2547).
--define(wxAuiPaneInfo_FloatingSize_1, 2548).
--define(wxAuiPaneInfo_FloatingSize_2, 2549).
--define(wxAuiPaneInfo_Gripper, 2550).
--define(wxAuiPaneInfo_GripperTop, 2551).
--define(wxAuiPaneInfo_HasBorder, 2552).
--define(wxAuiPaneInfo_HasCaption, 2553).
--define(wxAuiPaneInfo_HasCloseButton, 2554).
--define(wxAuiPaneInfo_HasFlag, 2555).
--define(wxAuiPaneInfo_HasGripper, 2556).
--define(wxAuiPaneInfo_HasGripperTop, 2557).
--define(wxAuiPaneInfo_HasMaximizeButton, 2558).
--define(wxAuiPaneInfo_HasMinimizeButton, 2559).
--define(wxAuiPaneInfo_HasPinButton, 2560).
--define(wxAuiPaneInfo_Hide, 2561).
--define(wxAuiPaneInfo_IsBottomDockable, 2562).
--define(wxAuiPaneInfo_IsDocked, 2563).
--define(wxAuiPaneInfo_IsFixed, 2564).
--define(wxAuiPaneInfo_IsFloatable, 2565).
--define(wxAuiPaneInfo_IsFloating, 2566).
--define(wxAuiPaneInfo_IsLeftDockable, 2567).
--define(wxAuiPaneInfo_IsMovable, 2568).
--define(wxAuiPaneInfo_IsOk, 2569).
--define(wxAuiPaneInfo_IsResizable, 2570).
--define(wxAuiPaneInfo_IsRightDockable, 2571).
--define(wxAuiPaneInfo_IsShown, 2572).
--define(wxAuiPaneInfo_IsToolbar, 2573).
--define(wxAuiPaneInfo_IsTopDockable, 2574).
--define(wxAuiPaneInfo_Layer, 2575).
--define(wxAuiPaneInfo_Left, 2576).
--define(wxAuiPaneInfo_LeftDockable, 2577).
--define(wxAuiPaneInfo_MaxSize_1, 2578).
--define(wxAuiPaneInfo_MaxSize_2, 2579).
--define(wxAuiPaneInfo_MaximizeButton, 2580).
--define(wxAuiPaneInfo_MinSize_1, 2581).
--define(wxAuiPaneInfo_MinSize_2, 2582).
--define(wxAuiPaneInfo_MinimizeButton, 2583).
--define(wxAuiPaneInfo_Movable, 2584).
--define(wxAuiPaneInfo_Name, 2585).
--define(wxAuiPaneInfo_PaneBorder, 2586).
--define(wxAuiPaneInfo_PinButton, 2587).
--define(wxAuiPaneInfo_Position, 2588).
--define(wxAuiPaneInfo_Resizable, 2589).
--define(wxAuiPaneInfo_Right, 2590).
--define(wxAuiPaneInfo_RightDockable, 2591).
--define(wxAuiPaneInfo_Row, 2592).
--define(wxAuiPaneInfo_SafeSet, 2593).
--define(wxAuiPaneInfo_SetFlag, 2594).
--define(wxAuiPaneInfo_Show, 2595).
--define(wxAuiPaneInfo_ToolbarPane, 2596).
--define(wxAuiPaneInfo_Top, 2597).
--define(wxAuiPaneInfo_TopDockable, 2598).
--define(wxAuiPaneInfo_Window, 2599).
--define(wxAuiPaneInfo_GetWindow, 2600).
--define(wxAuiPaneInfo_GetFrame, 2601).
--define(wxAuiPaneInfo_GetDirection, 2602).
--define(wxAuiPaneInfo_GetLayer, 2603).
--define(wxAuiPaneInfo_GetRow, 2604).
--define(wxAuiPaneInfo_GetPosition, 2605).
--define(wxAuiPaneInfo_GetFloatingPosition, 2606).
--define(wxAuiPaneInfo_GetFloatingSize, 2607).
--define(wxAuiPaneInfo_destroy, 2608).
--define(wxAuiNotebook_new_0, 2609).
--define(wxAuiNotebook_new_2, 2610).
--define(wxAuiNotebook_AddPage_3, 2611).
--define(wxAuiNotebook_AddPage_4, 2612).
--define(wxAuiNotebook_Create_2, 2613).
--define(wxAuiNotebook_Create_3, 2614).
--define(wxAuiNotebook_DeletePage, 2615).
--define(wxAuiNotebook_GetArtProvider, 2616).
--define(wxAuiNotebook_GetPage, 2617).
--define(wxAuiNotebook_GetPageBitmap, 2618).
--define(wxAuiNotebook_GetPageCount, 2619).
--define(wxAuiNotebook_GetPageIndex, 2620).
--define(wxAuiNotebook_GetPageText, 2621).
--define(wxAuiNotebook_GetSelection, 2622).
--define(wxAuiNotebook_InsertPage_4, 2623).
--define(wxAuiNotebook_InsertPage_5, 2624).
--define(wxAuiNotebook_RemovePage, 2625).
--define(wxAuiNotebook_SetArtProvider, 2626).
--define(wxAuiNotebook_SetFont, 2627).
--define(wxAuiNotebook_SetPageBitmap, 2628).
--define(wxAuiNotebook_SetPageText, 2629).
--define(wxAuiNotebook_SetSelection, 2630).
--define(wxAuiNotebook_SetTabCtrlHeight, 2631).
--define(wxAuiNotebook_SetUniformBitmapSize, 2632).
--define(wxAuiNotebook_destroy, 2633).
--define(wxAuiTabArt_SetFlags, 2634).
--define(wxAuiTabArt_SetMeasuringFont, 2635).
--define(wxAuiTabArt_SetNormalFont, 2636).
--define(wxAuiTabArt_SetSelectedFont, 2637).
--define(wxAuiTabArt_SetColour, 2638).
--define(wxAuiTabArt_SetActiveColour, 2639).
--define(wxAuiDockArt_GetColour, 2640).
--define(wxAuiDockArt_GetFont, 2641).
--define(wxAuiDockArt_GetMetric, 2642).
--define(wxAuiDockArt_SetColour, 2643).
--define(wxAuiDockArt_SetFont, 2644).
--define(wxAuiDockArt_SetMetric, 2645).
--define(wxAuiSimpleTabArt_new, 2646).
--define(wxAuiSimpleTabArt_destroy, 2647).
--define(wxMDIParentFrame_new_0, 2648).
--define(wxMDIParentFrame_new_4, 2649).
--define(wxMDIParentFrame_destruct, 2650).
--define(wxMDIParentFrame_ActivateNext, 2651).
--define(wxMDIParentFrame_ActivatePrevious, 2652).
--define(wxMDIParentFrame_ArrangeIcons, 2653).
--define(wxMDIParentFrame_Cascade, 2654).
--define(wxMDIParentFrame_Create, 2655).
--define(wxMDIParentFrame_GetActiveChild, 2656).
--define(wxMDIParentFrame_GetClientWindow, 2657).
--define(wxMDIParentFrame_Tile, 2658).
--define(wxMDIChildFrame_new_0, 2659).
--define(wxMDIChildFrame_new_4, 2660).
--define(wxMDIChildFrame_destruct, 2661).
--define(wxMDIChildFrame_Activate, 2662).
--define(wxMDIChildFrame_Create, 2663).
--define(wxMDIChildFrame_Maximize, 2664).
--define(wxMDIChildFrame_Restore, 2665).
--define(wxMDIClientWindow_new, 2666).
--define(wxMDIClientWindow_CreateClient, 2667).
--define(wxMDIClientWindow_destroy, 2668).
--define(wxLayoutAlgorithm_new, 2669).
--define(wxLayoutAlgorithm_destruct, 2670).
--define(wxLayoutAlgorithm_LayoutFrame, 2671).
--define(wxLayoutAlgorithm_LayoutMDIFrame, 2672).
--define(wxLayoutAlgorithm_LayoutWindow, 2673).
--define(wxEvent_GetId, 2674).
--define(wxEvent_GetSkipped, 2675).
--define(wxEvent_GetTimestamp, 2676).
--define(wxEvent_IsCommandEvent, 2677).
--define(wxEvent_ResumePropagation, 2678).
--define(wxEvent_ShouldPropagate, 2679).
--define(wxEvent_Skip, 2680).
--define(wxEvent_StopPropagation, 2681).
--define(wxCommandEvent_getClientData, 2682).
--define(wxCommandEvent_GetExtraLong, 2683).
--define(wxCommandEvent_GetInt, 2684).
--define(wxCommandEvent_GetSelection, 2685).
--define(wxCommandEvent_GetString, 2686).
--define(wxCommandEvent_IsChecked, 2687).
--define(wxCommandEvent_IsSelection, 2688).
--define(wxCommandEvent_SetInt, 2689).
--define(wxCommandEvent_SetString, 2690).
--define(wxScrollEvent_GetOrientation, 2691).
--define(wxScrollEvent_GetPosition, 2692).
--define(wxScrollWinEvent_GetOrientation, 2693).
--define(wxScrollWinEvent_GetPosition, 2694).
--define(wxMouseEvent_AltDown, 2695).
--define(wxMouseEvent_Button, 2696).
--define(wxMouseEvent_ButtonDClick, 2697).
--define(wxMouseEvent_ButtonDown, 2698).
--define(wxMouseEvent_ButtonUp, 2699).
--define(wxMouseEvent_CmdDown, 2700).
--define(wxMouseEvent_ControlDown, 2701).
--define(wxMouseEvent_Dragging, 2702).
--define(wxMouseEvent_Entering, 2703).
--define(wxMouseEvent_GetButton, 2704).
--define(wxMouseEvent_GetPosition, 2705).
--define(wxMouseEvent_GetLogicalPosition, 2707).
--define(wxMouseEvent_GetLinesPerAction, 2708).
--define(wxMouseEvent_GetWheelRotation, 2709).
--define(wxMouseEvent_GetWheelDelta, 2710).
--define(wxMouseEvent_GetX, 2711).
--define(wxMouseEvent_GetY, 2712).
--define(wxMouseEvent_IsButton, 2713).
--define(wxMouseEvent_IsPageScroll, 2714).
--define(wxMouseEvent_Leaving, 2715).
--define(wxMouseEvent_LeftDClick, 2716).
--define(wxMouseEvent_LeftDown, 2717).
--define(wxMouseEvent_LeftIsDown, 2718).
--define(wxMouseEvent_LeftUp, 2719).
--define(wxMouseEvent_MetaDown, 2720).
--define(wxMouseEvent_MiddleDClick, 2721).
--define(wxMouseEvent_MiddleDown, 2722).
--define(wxMouseEvent_MiddleIsDown, 2723).
--define(wxMouseEvent_MiddleUp, 2724).
--define(wxMouseEvent_Moving, 2725).
--define(wxMouseEvent_RightDClick, 2726).
--define(wxMouseEvent_RightDown, 2727).
--define(wxMouseEvent_RightIsDown, 2728).
--define(wxMouseEvent_RightUp, 2729).
--define(wxMouseEvent_ShiftDown, 2730).
--define(wxMouseEvent_GetWheelAxis, 2731).
--define(wxMouseEvent_Aux1DClick, 2732).
--define(wxMouseEvent_Aux1Down, 2733).
--define(wxMouseEvent_Aux1Up, 2734).
--define(wxMouseEvent_Aux2DClick, 2735).
--define(wxMouseEvent_Aux2Down, 2736).
--define(wxMouseEvent_Aux2Up, 2737).
--define(wxSetCursorEvent_GetCursor, 2738).
--define(wxSetCursorEvent_GetX, 2739).
--define(wxSetCursorEvent_GetY, 2740).
--define(wxSetCursorEvent_HasCursor, 2741).
--define(wxSetCursorEvent_SetCursor, 2742).
--define(wxKeyEvent_AltDown, 2743).
--define(wxKeyEvent_CmdDown, 2744).
--define(wxKeyEvent_ControlDown, 2745).
--define(wxKeyEvent_GetKeyCode, 2746).
--define(wxKeyEvent_GetModifiers, 2747).
--define(wxKeyEvent_GetPosition, 2748).
--define(wxKeyEvent_GetRawKeyCode, 2750).
--define(wxKeyEvent_GetRawKeyFlags, 2751).
--define(wxKeyEvent_GetUnicodeKey, 2752).
--define(wxKeyEvent_GetX, 2753).
--define(wxKeyEvent_GetY, 2754).
--define(wxKeyEvent_HasModifiers, 2755).
--define(wxKeyEvent_MetaDown, 2756).
--define(wxKeyEvent_ShiftDown, 2757).
--define(wxSizeEvent_GetSize, 2758).
--define(wxSizeEvent_GetRect, 2759).
--define(wxMoveEvent_GetPosition, 2760).
--define(wxMoveEvent_GetRect, 2761).
--define(wxEraseEvent_GetDC, 2762).
--define(wxFocusEvent_GetWindow, 2763).
--define(wxChildFocusEvent_GetWindow, 2764).
--define(wxMenuEvent_GetMenu, 2765).
--define(wxMenuEvent_GetMenuId, 2766).
--define(wxMenuEvent_IsPopup, 2767).
--define(wxCloseEvent_CanVeto, 2768).
--define(wxCloseEvent_GetLoggingOff, 2769).
--define(wxCloseEvent_SetCanVeto, 2770).
--define(wxCloseEvent_SetLoggingOff, 2771).
--define(wxCloseEvent_Veto, 2772).
--define(wxShowEvent_SetShow, 2773).
--define(wxShowEvent_IsShown, 2774).
--define(wxIconizeEvent_IsIconized, 2775).
--define(wxJoystickEvent_ButtonDown, 2776).
--define(wxJoystickEvent_ButtonIsDown, 2777).
--define(wxJoystickEvent_ButtonUp, 2778).
--define(wxJoystickEvent_GetButtonChange, 2779).
--define(wxJoystickEvent_GetButtonState, 2780).
--define(wxJoystickEvent_GetJoystick, 2781).
--define(wxJoystickEvent_GetPosition, 2782).
--define(wxJoystickEvent_GetZPosition, 2783).
--define(wxJoystickEvent_IsButton, 2784).
--define(wxJoystickEvent_IsMove, 2785).
--define(wxJoystickEvent_IsZMove, 2786).
--define(wxUpdateUIEvent_CanUpdate, 2787).
--define(wxUpdateUIEvent_Check, 2788).
--define(wxUpdateUIEvent_Enable, 2789).
--define(wxUpdateUIEvent_Show, 2790).
--define(wxUpdateUIEvent_GetChecked, 2791).
--define(wxUpdateUIEvent_GetEnabled, 2792).
--define(wxUpdateUIEvent_GetShown, 2793).
--define(wxUpdateUIEvent_GetSetChecked, 2794).
--define(wxUpdateUIEvent_GetSetEnabled, 2795).
--define(wxUpdateUIEvent_GetSetShown, 2796).
--define(wxUpdateUIEvent_GetSetText, 2797).
--define(wxUpdateUIEvent_GetText, 2798).
--define(wxUpdateUIEvent_GetMode, 2799).
--define(wxUpdateUIEvent_GetUpdateInterval, 2800).
--define(wxUpdateUIEvent_ResetUpdateTime, 2801).
--define(wxUpdateUIEvent_SetMode, 2802).
--define(wxUpdateUIEvent_SetText, 2803).
--define(wxUpdateUIEvent_SetUpdateInterval, 2804).
--define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2805).
--define(wxPaletteChangedEvent_SetChangedWindow, 2806).
--define(wxPaletteChangedEvent_GetChangedWindow, 2807).
--define(wxQueryNewPaletteEvent_SetPaletteRealized, 2808).
--define(wxQueryNewPaletteEvent_GetPaletteRealized, 2809).
--define(wxNavigationKeyEvent_GetDirection, 2810).
--define(wxNavigationKeyEvent_SetDirection, 2811).
--define(wxNavigationKeyEvent_IsWindowChange, 2812).
--define(wxNavigationKeyEvent_SetWindowChange, 2813).
--define(wxNavigationKeyEvent_IsFromTab, 2814).
--define(wxNavigationKeyEvent_SetFromTab, 2815).
--define(wxNavigationKeyEvent_GetCurrentFocus, 2816).
--define(wxNavigationKeyEvent_SetCurrentFocus, 2817).
--define(wxHelpEvent_GetOrigin, 2818).
--define(wxHelpEvent_GetPosition, 2819).
--define(wxHelpEvent_SetOrigin, 2820).
--define(wxHelpEvent_SetPosition, 2821).
--define(wxContextMenuEvent_GetPosition, 2822).
--define(wxContextMenuEvent_SetPosition, 2823).
--define(wxIdleEvent_GetMode, 2824).
--define(wxIdleEvent_RequestMore, 2825).
--define(wxIdleEvent_MoreRequested, 2826).
--define(wxIdleEvent_SetMode, 2827).
--define(wxGridEvent_AltDown, 2828).
--define(wxGridEvent_ControlDown, 2829).
--define(wxGridEvent_GetCol, 2830).
--define(wxGridEvent_GetPosition, 2831).
--define(wxGridEvent_GetRow, 2832).
--define(wxGridEvent_MetaDown, 2833).
--define(wxGridEvent_Selecting, 2834).
--define(wxGridEvent_ShiftDown, 2835).
--define(wxNotifyEvent_Allow, 2836).
--define(wxNotifyEvent_IsAllowed, 2837).
--define(wxNotifyEvent_Veto, 2838).
--define(wxSashEvent_GetEdge, 2839).
--define(wxSashEvent_GetDragRect, 2840).
--define(wxSashEvent_GetDragStatus, 2841).
--define(wxListEvent_GetCacheFrom, 2842).
--define(wxListEvent_GetCacheTo, 2843).
--define(wxListEvent_GetKeyCode, 2844).
--define(wxListEvent_GetIndex, 2845).
--define(wxListEvent_GetColumn, 2846).
--define(wxListEvent_GetPoint, 2847).
--define(wxListEvent_GetLabel, 2848).
--define(wxListEvent_GetText, 2849).
--define(wxListEvent_GetImage, 2850).
--define(wxListEvent_GetData, 2851).
--define(wxListEvent_GetMask, 2852).
--define(wxListEvent_GetItem, 2853).
--define(wxListEvent_IsEditCancelled, 2854).
--define(wxDateEvent_GetDate, 2855).
--define(wxCalendarEvent_GetWeekDay, 2856).
--define(wxCalendarEvent_GetDate, 2857).
--define(wxFileDirPickerEvent_GetPath, 2858).
--define(wxColourPickerEvent_GetColour, 2859).
--define(wxFontPickerEvent_GetFont, 2860).
--define(wxStyledTextEvent_GetPosition, 2861).
--define(wxStyledTextEvent_GetKey, 2862).
--define(wxStyledTextEvent_GetModifiers, 2863).
--define(wxStyledTextEvent_GetModificationType, 2864).
--define(wxStyledTextEvent_GetText, 2865).
--define(wxStyledTextEvent_GetLength, 2866).
--define(wxStyledTextEvent_GetLinesAdded, 2867).
--define(wxStyledTextEvent_GetLine, 2868).
--define(wxStyledTextEvent_GetFoldLevelNow, 2869).
--define(wxStyledTextEvent_GetFoldLevelPrev, 2870).
--define(wxStyledTextEvent_GetMargin, 2871).
--define(wxStyledTextEvent_GetMessage, 2872).
--define(wxStyledTextEvent_GetWParam, 2873).
--define(wxStyledTextEvent_GetLParam, 2874).
--define(wxStyledTextEvent_GetListType, 2875).
--define(wxStyledTextEvent_GetX, 2876).
--define(wxStyledTextEvent_GetY, 2877).
--define(wxStyledTextEvent_GetDragText, 2878).
--define(wxStyledTextEvent_GetDragAllowMove, 2879).
--define(wxStyledTextEvent_GetDragResult, 2880).
--define(wxStyledTextEvent_GetShift, 2881).
--define(wxStyledTextEvent_GetControl, 2882).
--define(wxStyledTextEvent_GetAlt, 2883).
--define(utils_wxGetKeyState, 2884).
--define(utils_wxGetMousePosition, 2885).
--define(utils_wxGetMouseState, 2886).
--define(utils_wxSetDetectableAutoRepeat, 2887).
--define(utils_wxBell, 2888).
--define(utils_wxFindMenuItemId, 2889).
--define(utils_wxFindWindowAtPoint, 2890).
--define(utils_wxBeginBusyCursor, 2891).
--define(utils_wxEndBusyCursor, 2892).
--define(utils_wxIsBusy, 2893).
--define(utils_wxShutdown, 2894).
--define(utils_wxShell, 2895).
--define(utils_wxLaunchDefaultBrowser, 2896).
--define(utils_wxGetEmailAddress, 2897).
--define(utils_wxGetUserId, 2898).
--define(utils_wxGetHomeDir, 2899).
--define(utils_wxNewId, 2900).
--define(utils_wxRegisterId, 2901).
--define(utils_wxGetCurrentId, 2902).
--define(utils_wxGetOsDescription, 2903).
--define(utils_wxIsPlatformLittleEndian, 2904).
--define(utils_wxIsPlatform64Bit, 2905).
--define(gdicmn_wxDisplaySize, 2906).
--define(gdicmn_wxSetCursor, 2907).
--define(wxPrintout_new, 2908).
--define(wxPrintout_destruct, 2909).
--define(wxPrintout_GetDC, 2910).
--define(wxPrintout_GetPageSizeMM, 2911).
--define(wxPrintout_GetPageSizePixels, 2912).
--define(wxPrintout_GetPaperRectPixels, 2913).
--define(wxPrintout_GetPPIPrinter, 2914).
--define(wxPrintout_GetPPIScreen, 2915).
--define(wxPrintout_GetTitle, 2916).
--define(wxPrintout_IsPreview, 2917).
--define(wxPrintout_FitThisSizeToPaper, 2918).
--define(wxPrintout_FitThisSizeToPage, 2919).
--define(wxPrintout_FitThisSizeToPageMargins, 2920).
--define(wxPrintout_MapScreenSizeToPaper, 2921).
--define(wxPrintout_MapScreenSizeToPage, 2922).
--define(wxPrintout_MapScreenSizeToPageMargins, 2923).
--define(wxPrintout_MapScreenSizeToDevice, 2924).
--define(wxPrintout_GetLogicalPaperRect, 2925).
--define(wxPrintout_GetLogicalPageRect, 2926).
--define(wxPrintout_GetLogicalPageMarginsRect, 2927).
--define(wxPrintout_SetLogicalOrigin, 2928).
--define(wxPrintout_OffsetLogicalOrigin, 2929).
--define(wxStyledTextCtrl_new_2, 2930).
--define(wxStyledTextCtrl_new_0, 2931).
--define(wxStyledTextCtrl_destruct, 2932).
--define(wxStyledTextCtrl_Create, 2933).
--define(wxStyledTextCtrl_AddText, 2934).
--define(wxStyledTextCtrl_InsertText, 2935).
--define(wxStyledTextCtrl_ClearAll, 2936).
--define(wxStyledTextCtrl_ClearDocumentStyle, 2937).
--define(wxStyledTextCtrl_GetLength, 2938).
--define(wxStyledTextCtrl_GetCharAt, 2939).
--define(wxStyledTextCtrl_GetCurrentPos, 2940).
--define(wxStyledTextCtrl_GetAnchor, 2941).
--define(wxStyledTextCtrl_GetStyleAt, 2942).
--define(wxStyledTextCtrl_Redo, 2943).
--define(wxStyledTextCtrl_SetUndoCollection, 2944).
--define(wxStyledTextCtrl_SelectAll, 2945).
--define(wxStyledTextCtrl_SetSavePoint, 2946).
--define(wxStyledTextCtrl_CanRedo, 2947).
--define(wxStyledTextCtrl_MarkerLineFromHandle, 2948).
--define(wxStyledTextCtrl_MarkerDeleteHandle, 2949).
--define(wxStyledTextCtrl_GetUndoCollection, 2950).
--define(wxStyledTextCtrl_GetViewWhiteSpace, 2951).
--define(wxStyledTextCtrl_SetViewWhiteSpace, 2952).
--define(wxStyledTextCtrl_PositionFromPoint, 2953).
--define(wxStyledTextCtrl_PositionFromPointClose, 2954).
--define(wxStyledTextCtrl_GotoLine, 2955).
--define(wxStyledTextCtrl_GotoPos, 2956).
--define(wxStyledTextCtrl_SetAnchor, 2957).
--define(wxStyledTextCtrl_GetCurLine, 2958).
--define(wxStyledTextCtrl_GetEndStyled, 2959).
--define(wxStyledTextCtrl_ConvertEOLs, 2960).
--define(wxStyledTextCtrl_GetEOLMode, 2961).
--define(wxStyledTextCtrl_SetEOLMode, 2962).
--define(wxStyledTextCtrl_StartStyling, 2963).
--define(wxStyledTextCtrl_SetStyling, 2964).
--define(wxStyledTextCtrl_GetBufferedDraw, 2965).
--define(wxStyledTextCtrl_SetBufferedDraw, 2966).
--define(wxStyledTextCtrl_SetTabWidth, 2967).
--define(wxStyledTextCtrl_GetTabWidth, 2968).
--define(wxStyledTextCtrl_SetCodePage, 2969).
--define(wxStyledTextCtrl_MarkerDefine, 2970).
--define(wxStyledTextCtrl_MarkerSetForeground, 2971).
--define(wxStyledTextCtrl_MarkerSetBackground, 2972).
--define(wxStyledTextCtrl_MarkerAdd, 2973).
--define(wxStyledTextCtrl_MarkerDelete, 2974).
--define(wxStyledTextCtrl_MarkerDeleteAll, 2975).
--define(wxStyledTextCtrl_MarkerGet, 2976).
--define(wxStyledTextCtrl_MarkerNext, 2977).
--define(wxStyledTextCtrl_MarkerPrevious, 2978).
--define(wxStyledTextCtrl_MarkerDefineBitmap, 2979).
--define(wxStyledTextCtrl_MarkerAddSet, 2980).
--define(wxStyledTextCtrl_MarkerSetAlpha, 2981).
--define(wxStyledTextCtrl_SetMarginType, 2982).
--define(wxStyledTextCtrl_GetMarginType, 2983).
--define(wxStyledTextCtrl_SetMarginWidth, 2984).
--define(wxStyledTextCtrl_GetMarginWidth, 2985).
--define(wxStyledTextCtrl_SetMarginMask, 2986).
--define(wxStyledTextCtrl_GetMarginMask, 2987).
--define(wxStyledTextCtrl_SetMarginSensitive, 2988).
--define(wxStyledTextCtrl_GetMarginSensitive, 2989).
--define(wxStyledTextCtrl_StyleClearAll, 2990).
--define(wxStyledTextCtrl_StyleSetForeground, 2991).
--define(wxStyledTextCtrl_StyleSetBackground, 2992).
--define(wxStyledTextCtrl_StyleSetBold, 2993).
--define(wxStyledTextCtrl_StyleSetItalic, 2994).
--define(wxStyledTextCtrl_StyleSetSize, 2995).
--define(wxStyledTextCtrl_StyleSetFaceName, 2996).
--define(wxStyledTextCtrl_StyleSetEOLFilled, 2997).
--define(wxStyledTextCtrl_StyleResetDefault, 2998).
--define(wxStyledTextCtrl_StyleSetUnderline, 2999).
--define(wxStyledTextCtrl_StyleSetCase, 3000).
--define(wxStyledTextCtrl_StyleSetHotSpot, 3001).
--define(wxStyledTextCtrl_SetSelForeground, 3002).
--define(wxStyledTextCtrl_SetSelBackground, 3003).
--define(wxStyledTextCtrl_GetSelAlpha, 3004).
--define(wxStyledTextCtrl_SetSelAlpha, 3005).
--define(wxStyledTextCtrl_SetCaretForeground, 3006).
--define(wxStyledTextCtrl_CmdKeyAssign, 3007).
--define(wxStyledTextCtrl_CmdKeyClear, 3008).
--define(wxStyledTextCtrl_CmdKeyClearAll, 3009).
--define(wxStyledTextCtrl_SetStyleBytes, 3010).
--define(wxStyledTextCtrl_StyleSetVisible, 3011).
--define(wxStyledTextCtrl_GetCaretPeriod, 3012).
--define(wxStyledTextCtrl_SetCaretPeriod, 3013).
--define(wxStyledTextCtrl_SetWordChars, 3014).
--define(wxStyledTextCtrl_BeginUndoAction, 3015).
--define(wxStyledTextCtrl_EndUndoAction, 3016).
--define(wxStyledTextCtrl_IndicatorSetStyle, 3017).
--define(wxStyledTextCtrl_IndicatorGetStyle, 3018).
--define(wxStyledTextCtrl_IndicatorSetForeground, 3019).
--define(wxStyledTextCtrl_IndicatorGetForeground, 3020).
--define(wxStyledTextCtrl_SetWhitespaceForeground, 3021).
--define(wxStyledTextCtrl_SetWhitespaceBackground, 3022).
--define(wxStyledTextCtrl_GetStyleBits, 3023).
--define(wxStyledTextCtrl_SetLineState, 3024).
--define(wxStyledTextCtrl_GetLineState, 3025).
--define(wxStyledTextCtrl_GetMaxLineState, 3026).
--define(wxStyledTextCtrl_GetCaretLineVisible, 3027).
--define(wxStyledTextCtrl_SetCaretLineVisible, 3028).
--define(wxStyledTextCtrl_GetCaretLineBackground, 3029).
--define(wxStyledTextCtrl_SetCaretLineBackground, 3030).
--define(wxStyledTextCtrl_AutoCompShow, 3031).
--define(wxStyledTextCtrl_AutoCompCancel, 3032).
--define(wxStyledTextCtrl_AutoCompActive, 3033).
--define(wxStyledTextCtrl_AutoCompPosStart, 3034).
--define(wxStyledTextCtrl_AutoCompComplete, 3035).
--define(wxStyledTextCtrl_AutoCompStops, 3036).
--define(wxStyledTextCtrl_AutoCompSetSeparator, 3037).
--define(wxStyledTextCtrl_AutoCompGetSeparator, 3038).
--define(wxStyledTextCtrl_AutoCompSelect, 3039).
--define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3040).
--define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3041).
--define(wxStyledTextCtrl_AutoCompSetFillUps, 3042).
--define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3043).
--define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3044).
--define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3045).
--define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3046).
--define(wxStyledTextCtrl_UserListShow, 3047).
--define(wxStyledTextCtrl_AutoCompSetAutoHide, 3048).
--define(wxStyledTextCtrl_AutoCompGetAutoHide, 3049).
--define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3050).
--define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3051).
--define(wxStyledTextCtrl_RegisterImage, 3052).
--define(wxStyledTextCtrl_ClearRegisteredImages, 3053).
--define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3054).
--define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3055).
--define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3056).
--define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3057).
--define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3058).
--define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3059).
--define(wxStyledTextCtrl_SetIndent, 3060).
--define(wxStyledTextCtrl_GetIndent, 3061).
--define(wxStyledTextCtrl_SetUseTabs, 3062).
--define(wxStyledTextCtrl_GetUseTabs, 3063).
--define(wxStyledTextCtrl_SetLineIndentation, 3064).
--define(wxStyledTextCtrl_GetLineIndentation, 3065).
--define(wxStyledTextCtrl_GetLineIndentPosition, 3066).
--define(wxStyledTextCtrl_GetColumn, 3067).
--define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3068).
--define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3069).
--define(wxStyledTextCtrl_SetIndentationGuides, 3070).
--define(wxStyledTextCtrl_GetIndentationGuides, 3071).
--define(wxStyledTextCtrl_SetHighlightGuide, 3072).
--define(wxStyledTextCtrl_GetHighlightGuide, 3073).
--define(wxStyledTextCtrl_GetLineEndPosition, 3074).
--define(wxStyledTextCtrl_GetCodePage, 3075).
--define(wxStyledTextCtrl_GetCaretForeground, 3076).
--define(wxStyledTextCtrl_GetReadOnly, 3077).
--define(wxStyledTextCtrl_SetCurrentPos, 3078).
--define(wxStyledTextCtrl_SetSelectionStart, 3079).
--define(wxStyledTextCtrl_GetSelectionStart, 3080).
--define(wxStyledTextCtrl_SetSelectionEnd, 3081).
--define(wxStyledTextCtrl_GetSelectionEnd, 3082).
--define(wxStyledTextCtrl_SetPrintMagnification, 3083).
--define(wxStyledTextCtrl_GetPrintMagnification, 3084).
--define(wxStyledTextCtrl_SetPrintColourMode, 3085).
--define(wxStyledTextCtrl_GetPrintColourMode, 3086).
--define(wxStyledTextCtrl_FindText, 3087).
--define(wxStyledTextCtrl_FormatRange, 3088).
--define(wxStyledTextCtrl_GetFirstVisibleLine, 3089).
--define(wxStyledTextCtrl_GetLine, 3090).
--define(wxStyledTextCtrl_GetLineCount, 3091).
--define(wxStyledTextCtrl_SetMarginLeft, 3092).
--define(wxStyledTextCtrl_GetMarginLeft, 3093).
--define(wxStyledTextCtrl_SetMarginRight, 3094).
--define(wxStyledTextCtrl_GetMarginRight, 3095).
--define(wxStyledTextCtrl_GetModify, 3096).
--define(wxStyledTextCtrl_SetSelection, 3097).
--define(wxStyledTextCtrl_GetSelectedText, 3098).
--define(wxStyledTextCtrl_GetTextRange, 3099).
--define(wxStyledTextCtrl_HideSelection, 3100).
--define(wxStyledTextCtrl_LineFromPosition, 3101).
--define(wxStyledTextCtrl_PositionFromLine, 3102).
--define(wxStyledTextCtrl_LineScroll, 3103).
--define(wxStyledTextCtrl_EnsureCaretVisible, 3104).
--define(wxStyledTextCtrl_ReplaceSelection, 3105).
--define(wxStyledTextCtrl_SetReadOnly, 3106).
--define(wxStyledTextCtrl_CanPaste, 3107).
--define(wxStyledTextCtrl_CanUndo, 3108).
--define(wxStyledTextCtrl_EmptyUndoBuffer, 3109).
--define(wxStyledTextCtrl_Undo, 3110).
--define(wxStyledTextCtrl_Cut, 3111).
--define(wxStyledTextCtrl_Copy, 3112).
--define(wxStyledTextCtrl_Paste, 3113).
--define(wxStyledTextCtrl_Clear, 3114).
--define(wxStyledTextCtrl_SetText, 3115).
--define(wxStyledTextCtrl_GetText, 3116).
--define(wxStyledTextCtrl_GetTextLength, 3117).
--define(wxStyledTextCtrl_GetOvertype, 3118).
--define(wxStyledTextCtrl_SetCaretWidth, 3119).
--define(wxStyledTextCtrl_GetCaretWidth, 3120).
--define(wxStyledTextCtrl_SetTargetStart, 3121).
--define(wxStyledTextCtrl_GetTargetStart, 3122).
--define(wxStyledTextCtrl_SetTargetEnd, 3123).
--define(wxStyledTextCtrl_GetTargetEnd, 3124).
--define(wxStyledTextCtrl_ReplaceTarget, 3125).
--define(wxStyledTextCtrl_SearchInTarget, 3126).
--define(wxStyledTextCtrl_SetSearchFlags, 3127).
--define(wxStyledTextCtrl_GetSearchFlags, 3128).
--define(wxStyledTextCtrl_CallTipShow, 3129).
--define(wxStyledTextCtrl_CallTipCancel, 3130).
--define(wxStyledTextCtrl_CallTipActive, 3131).
--define(wxStyledTextCtrl_CallTipPosAtStart, 3132).
--define(wxStyledTextCtrl_CallTipSetHighlight, 3133).
--define(wxStyledTextCtrl_CallTipSetBackground, 3134).
--define(wxStyledTextCtrl_CallTipSetForeground, 3135).
--define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3136).
--define(wxStyledTextCtrl_CallTipUseStyle, 3137).
--define(wxStyledTextCtrl_VisibleFromDocLine, 3138).
--define(wxStyledTextCtrl_DocLineFromVisible, 3139).
--define(wxStyledTextCtrl_WrapCount, 3140).
--define(wxStyledTextCtrl_SetFoldLevel, 3141).
--define(wxStyledTextCtrl_GetFoldLevel, 3142).
--define(wxStyledTextCtrl_GetLastChild, 3143).
--define(wxStyledTextCtrl_GetFoldParent, 3144).
--define(wxStyledTextCtrl_ShowLines, 3145).
--define(wxStyledTextCtrl_HideLines, 3146).
--define(wxStyledTextCtrl_GetLineVisible, 3147).
--define(wxStyledTextCtrl_SetFoldExpanded, 3148).
--define(wxStyledTextCtrl_GetFoldExpanded, 3149).
--define(wxStyledTextCtrl_ToggleFold, 3150).
--define(wxStyledTextCtrl_EnsureVisible, 3151).
--define(wxStyledTextCtrl_SetFoldFlags, 3152).
--define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3153).
--define(wxStyledTextCtrl_SetTabIndents, 3154).
--define(wxStyledTextCtrl_GetTabIndents, 3155).
--define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3156).
--define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3157).
--define(wxStyledTextCtrl_SetMouseDwellTime, 3158).
--define(wxStyledTextCtrl_GetMouseDwellTime, 3159).
--define(wxStyledTextCtrl_WordStartPosition, 3160).
--define(wxStyledTextCtrl_WordEndPosition, 3161).
--define(wxStyledTextCtrl_SetWrapMode, 3162).
--define(wxStyledTextCtrl_GetWrapMode, 3163).
--define(wxStyledTextCtrl_SetWrapVisualFlags, 3164).
--define(wxStyledTextCtrl_GetWrapVisualFlags, 3165).
--define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3166).
--define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3167).
--define(wxStyledTextCtrl_SetWrapStartIndent, 3168).
--define(wxStyledTextCtrl_GetWrapStartIndent, 3169).
--define(wxStyledTextCtrl_SetLayoutCache, 3170).
--define(wxStyledTextCtrl_GetLayoutCache, 3171).
--define(wxStyledTextCtrl_SetScrollWidth, 3172).
--define(wxStyledTextCtrl_GetScrollWidth, 3173).
--define(wxStyledTextCtrl_TextWidth, 3174).
--define(wxStyledTextCtrl_GetEndAtLastLine, 3175).
--define(wxStyledTextCtrl_TextHeight, 3176).
--define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3177).
--define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3178).
--define(wxStyledTextCtrl_AppendText, 3179).
--define(wxStyledTextCtrl_GetTwoPhaseDraw, 3180).
--define(wxStyledTextCtrl_SetTwoPhaseDraw, 3181).
--define(wxStyledTextCtrl_TargetFromSelection, 3182).
--define(wxStyledTextCtrl_LinesJoin, 3183).
--define(wxStyledTextCtrl_LinesSplit, 3184).
--define(wxStyledTextCtrl_SetFoldMarginColour, 3185).
--define(wxStyledTextCtrl_SetFoldMarginHiColour, 3186).
--define(wxStyledTextCtrl_LineDown, 3187).
--define(wxStyledTextCtrl_LineDownExtend, 3188).
--define(wxStyledTextCtrl_LineUp, 3189).
--define(wxStyledTextCtrl_LineUpExtend, 3190).
--define(wxStyledTextCtrl_CharLeft, 3191).
--define(wxStyledTextCtrl_CharLeftExtend, 3192).
--define(wxStyledTextCtrl_CharRight, 3193).
--define(wxStyledTextCtrl_CharRightExtend, 3194).
--define(wxStyledTextCtrl_WordLeft, 3195).
--define(wxStyledTextCtrl_WordLeftExtend, 3196).
--define(wxStyledTextCtrl_WordRight, 3197).
--define(wxStyledTextCtrl_WordRightExtend, 3198).
--define(wxStyledTextCtrl_Home, 3199).
--define(wxStyledTextCtrl_HomeExtend, 3200).
--define(wxStyledTextCtrl_LineEnd, 3201).
--define(wxStyledTextCtrl_LineEndExtend, 3202).
--define(wxStyledTextCtrl_DocumentStart, 3203).
--define(wxStyledTextCtrl_DocumentStartExtend, 3204).
--define(wxStyledTextCtrl_DocumentEnd, 3205).
--define(wxStyledTextCtrl_DocumentEndExtend, 3206).
--define(wxStyledTextCtrl_PageUp, 3207).
--define(wxStyledTextCtrl_PageUpExtend, 3208).
--define(wxStyledTextCtrl_PageDown, 3209).
--define(wxStyledTextCtrl_PageDownExtend, 3210).
--define(wxStyledTextCtrl_EditToggleOvertype, 3211).
--define(wxStyledTextCtrl_Cancel, 3212).
--define(wxStyledTextCtrl_DeleteBack, 3213).
--define(wxStyledTextCtrl_Tab, 3214).
--define(wxStyledTextCtrl_BackTab, 3215).
--define(wxStyledTextCtrl_NewLine, 3216).
--define(wxStyledTextCtrl_FormFeed, 3217).
--define(wxStyledTextCtrl_VCHome, 3218).
--define(wxStyledTextCtrl_VCHomeExtend, 3219).
--define(wxStyledTextCtrl_ZoomIn, 3220).
--define(wxStyledTextCtrl_ZoomOut, 3221).
--define(wxStyledTextCtrl_DelWordLeft, 3222).
--define(wxStyledTextCtrl_DelWordRight, 3223).
--define(wxStyledTextCtrl_LineCut, 3224).
--define(wxStyledTextCtrl_LineDelete, 3225).
--define(wxStyledTextCtrl_LineTranspose, 3226).
--define(wxStyledTextCtrl_LineDuplicate, 3227).
--define(wxStyledTextCtrl_LowerCase, 3228).
--define(wxStyledTextCtrl_UpperCase, 3229).
--define(wxStyledTextCtrl_LineScrollDown, 3230).
--define(wxStyledTextCtrl_LineScrollUp, 3231).
--define(wxStyledTextCtrl_DeleteBackNotLine, 3232).
--define(wxStyledTextCtrl_HomeDisplay, 3233).
--define(wxStyledTextCtrl_HomeDisplayExtend, 3234).
--define(wxStyledTextCtrl_LineEndDisplay, 3235).
--define(wxStyledTextCtrl_LineEndDisplayExtend, 3236).
--define(wxStyledTextCtrl_HomeWrapExtend, 3237).
--define(wxStyledTextCtrl_LineEndWrap, 3238).
--define(wxStyledTextCtrl_LineEndWrapExtend, 3239).
--define(wxStyledTextCtrl_VCHomeWrap, 3240).
--define(wxStyledTextCtrl_VCHomeWrapExtend, 3241).
--define(wxStyledTextCtrl_LineCopy, 3242).
--define(wxStyledTextCtrl_MoveCaretInsideView, 3243).
--define(wxStyledTextCtrl_LineLength, 3244).
--define(wxStyledTextCtrl_BraceHighlight, 3245).
--define(wxStyledTextCtrl_BraceBadLight, 3246).
--define(wxStyledTextCtrl_BraceMatch, 3247).
--define(wxStyledTextCtrl_GetViewEOL, 3248).
--define(wxStyledTextCtrl_SetViewEOL, 3249).
--define(wxStyledTextCtrl_SetModEventMask, 3250).
--define(wxStyledTextCtrl_GetEdgeColumn, 3251).
--define(wxStyledTextCtrl_SetEdgeColumn, 3252).
--define(wxStyledTextCtrl_SetEdgeMode, 3253).
--define(wxStyledTextCtrl_GetEdgeMode, 3254).
--define(wxStyledTextCtrl_GetEdgeColour, 3255).
--define(wxStyledTextCtrl_SetEdgeColour, 3256).
--define(wxStyledTextCtrl_SearchAnchor, 3257).
--define(wxStyledTextCtrl_SearchNext, 3258).
--define(wxStyledTextCtrl_SearchPrev, 3259).
--define(wxStyledTextCtrl_LinesOnScreen, 3260).
--define(wxStyledTextCtrl_UsePopUp, 3261).
--define(wxStyledTextCtrl_SelectionIsRectangle, 3262).
--define(wxStyledTextCtrl_SetZoom, 3263).
--define(wxStyledTextCtrl_GetZoom, 3264).
--define(wxStyledTextCtrl_GetModEventMask, 3265).
--define(wxStyledTextCtrl_SetSTCFocus, 3266).
--define(wxStyledTextCtrl_GetSTCFocus, 3267).
--define(wxStyledTextCtrl_SetStatus, 3268).
--define(wxStyledTextCtrl_GetStatus, 3269).
--define(wxStyledTextCtrl_SetMouseDownCaptures, 3270).
--define(wxStyledTextCtrl_GetMouseDownCaptures, 3271).
--define(wxStyledTextCtrl_SetSTCCursor, 3272).
--define(wxStyledTextCtrl_GetSTCCursor, 3273).
--define(wxStyledTextCtrl_SetControlCharSymbol, 3274).
--define(wxStyledTextCtrl_GetControlCharSymbol, 3275).
--define(wxStyledTextCtrl_WordPartLeft, 3276).
--define(wxStyledTextCtrl_WordPartLeftExtend, 3277).
--define(wxStyledTextCtrl_WordPartRight, 3278).
--define(wxStyledTextCtrl_WordPartRightExtend, 3279).
--define(wxStyledTextCtrl_SetVisiblePolicy, 3280).
--define(wxStyledTextCtrl_DelLineLeft, 3281).
--define(wxStyledTextCtrl_DelLineRight, 3282).
--define(wxStyledTextCtrl_GetXOffset, 3283).
--define(wxStyledTextCtrl_ChooseCaretX, 3284).
--define(wxStyledTextCtrl_SetXCaretPolicy, 3285).
--define(wxStyledTextCtrl_SetYCaretPolicy, 3286).
--define(wxStyledTextCtrl_GetPrintWrapMode, 3287).
--define(wxStyledTextCtrl_SetHotspotActiveForeground, 3288).
--define(wxStyledTextCtrl_SetHotspotActiveBackground, 3289).
--define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3290).
--define(wxStyledTextCtrl_SetHotspotSingleLine, 3291).
--define(wxStyledTextCtrl_ParaDownExtend, 3292).
--define(wxStyledTextCtrl_ParaUp, 3293).
--define(wxStyledTextCtrl_ParaUpExtend, 3294).
--define(wxStyledTextCtrl_PositionBefore, 3295).
--define(wxStyledTextCtrl_PositionAfter, 3296).
--define(wxStyledTextCtrl_CopyRange, 3297).
--define(wxStyledTextCtrl_CopyText, 3298).
--define(wxStyledTextCtrl_SetSelectionMode, 3299).
--define(wxStyledTextCtrl_GetSelectionMode, 3300).
--define(wxStyledTextCtrl_LineDownRectExtend, 3301).
--define(wxStyledTextCtrl_LineUpRectExtend, 3302).
--define(wxStyledTextCtrl_CharLeftRectExtend, 3303).
--define(wxStyledTextCtrl_CharRightRectExtend, 3304).
--define(wxStyledTextCtrl_HomeRectExtend, 3305).
--define(wxStyledTextCtrl_VCHomeRectExtend, 3306).
--define(wxStyledTextCtrl_LineEndRectExtend, 3307).
--define(wxStyledTextCtrl_PageUpRectExtend, 3308).
--define(wxStyledTextCtrl_PageDownRectExtend, 3309).
--define(wxStyledTextCtrl_StutteredPageUp, 3310).
--define(wxStyledTextCtrl_StutteredPageUpExtend, 3311).
--define(wxStyledTextCtrl_StutteredPageDown, 3312).
--define(wxStyledTextCtrl_StutteredPageDownExtend, 3313).
--define(wxStyledTextCtrl_WordLeftEnd, 3314).
--define(wxStyledTextCtrl_WordLeftEndExtend, 3315).
--define(wxStyledTextCtrl_WordRightEnd, 3316).
--define(wxStyledTextCtrl_WordRightEndExtend, 3317).
--define(wxStyledTextCtrl_SetWhitespaceChars, 3318).
--define(wxStyledTextCtrl_SetCharsDefault, 3319).
--define(wxStyledTextCtrl_AutoCompGetCurrent, 3320).
--define(wxStyledTextCtrl_Allocate, 3321).
--define(wxStyledTextCtrl_FindColumn, 3322).
--define(wxStyledTextCtrl_GetCaretSticky, 3323).
--define(wxStyledTextCtrl_SetCaretSticky, 3324).
--define(wxStyledTextCtrl_ToggleCaretSticky, 3325).
--define(wxStyledTextCtrl_SetPasteConvertEndings, 3326).
--define(wxStyledTextCtrl_GetPasteConvertEndings, 3327).
--define(wxStyledTextCtrl_SelectionDuplicate, 3328).
--define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3329).
--define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3330).
--define(wxStyledTextCtrl_StartRecord, 3331).
--define(wxStyledTextCtrl_StopRecord, 3332).
--define(wxStyledTextCtrl_SetLexer, 3333).
--define(wxStyledTextCtrl_GetLexer, 3334).
--define(wxStyledTextCtrl_Colourise, 3335).
--define(wxStyledTextCtrl_SetProperty, 3336).
--define(wxStyledTextCtrl_SetKeyWords, 3337).
--define(wxStyledTextCtrl_SetLexerLanguage, 3338).
--define(wxStyledTextCtrl_GetProperty, 3339).
--define(wxStyledTextCtrl_GetStyleBitsNeeded, 3340).
--define(wxStyledTextCtrl_GetCurrentLine, 3341).
--define(wxStyledTextCtrl_StyleSetSpec, 3342).
--define(wxStyledTextCtrl_StyleSetFont, 3343).
--define(wxStyledTextCtrl_StyleSetFontAttr, 3344).
--define(wxStyledTextCtrl_StyleSetCharacterSet, 3345).
--define(wxStyledTextCtrl_StyleSetFontEncoding, 3346).
--define(wxStyledTextCtrl_CmdKeyExecute, 3347).
--define(wxStyledTextCtrl_SetMargins, 3348).
--define(wxStyledTextCtrl_GetSelection, 3349).
--define(wxStyledTextCtrl_PointFromPosition, 3350).
--define(wxStyledTextCtrl_ScrollToLine, 3351).
--define(wxStyledTextCtrl_ScrollToColumn, 3352).
--define(wxStyledTextCtrl_SetVScrollBar, 3353).
--define(wxStyledTextCtrl_SetHScrollBar, 3354).
--define(wxStyledTextCtrl_GetLastKeydownProcessed, 3355).
--define(wxStyledTextCtrl_SetLastKeydownProcessed, 3356).
--define(wxStyledTextCtrl_SaveFile, 3357).
--define(wxStyledTextCtrl_LoadFile, 3358).
--define(wxStyledTextCtrl_DoDragOver, 3359).
--define(wxStyledTextCtrl_DoDropText, 3360).
--define(wxStyledTextCtrl_GetUseAntiAliasing, 3361).
--define(wxStyledTextCtrl_AddTextRaw, 3362).
--define(wxStyledTextCtrl_InsertTextRaw, 3363).
--define(wxStyledTextCtrl_GetCurLineRaw, 3364).
--define(wxStyledTextCtrl_GetLineRaw, 3365).
--define(wxStyledTextCtrl_GetSelectedTextRaw, 3366).
--define(wxStyledTextCtrl_GetTextRangeRaw, 3367).
--define(wxStyledTextCtrl_SetTextRaw, 3368).
--define(wxStyledTextCtrl_GetTextRaw, 3369).
--define(wxStyledTextCtrl_AppendTextRaw, 3370).
--define(wxArtProvider_GetBitmap, 3371).
--define(wxArtProvider_GetIcon, 3372).
--define(wxTreeEvent_GetKeyCode, 3373).
--define(wxTreeEvent_GetItem, 3374).
--define(wxTreeEvent_GetKeyEvent, 3375).
--define(wxTreeEvent_GetLabel, 3376).
--define(wxTreeEvent_GetOldItem, 3377).
--define(wxTreeEvent_GetPoint, 3378).
--define(wxTreeEvent_IsEditCancelled, 3379).
--define(wxTreeEvent_SetToolTip, 3380).
--define(wxBookCtrlEvent_GetOldSelection, 3381).
--define(wxBookCtrlEvent_GetSelection, 3382).
--define(wxBookCtrlEvent_SetOldSelection, 3383).
--define(wxBookCtrlEvent_SetSelection, 3384).
--define(wxFileDataObject_new, 3385).
--define(wxFileDataObject_AddFile, 3386).
--define(wxFileDataObject_GetFilenames, 3387).
--define(wxFileDataObject_destroy, 3388).
--define(wxTextDataObject_new, 3389).
--define(wxTextDataObject_GetTextLength, 3390).
--define(wxTextDataObject_GetText, 3391).
--define(wxTextDataObject_SetText, 3392).
--define(wxTextDataObject_destroy, 3393).
--define(wxBitmapDataObject_new_1_1, 3394).
--define(wxBitmapDataObject_new_1_0, 3395).
--define(wxBitmapDataObject_GetBitmap, 3396).
--define(wxBitmapDataObject_SetBitmap, 3397).
--define(wxBitmapDataObject_destroy, 3398).
--define(wxClipboard_new, 3399).
--define(wxClipboard_destruct, 3400).
--define(wxClipboard_AddData, 3401).
--define(wxClipboard_Clear, 3402).
--define(wxClipboard_Close, 3403).
--define(wxClipboard_Flush, 3404).
--define(wxClipboard_GetData, 3405).
--define(wxClipboard_IsOpened, 3406).
--define(wxClipboard_Open, 3407).
--define(wxClipboard_SetData, 3408).
--define(wxClipboard_UsePrimarySelection, 3409).
--define(wxClipboard_IsSupported, 3410).
--define(wxClipboard_Get, 3411).
--define(wxSpinEvent_GetPosition, 3412).
--define(wxSpinEvent_SetPosition, 3413).
--define(wxSplitterWindow_new_0, 3414).
--define(wxSplitterWindow_new_2, 3415).
--define(wxSplitterWindow_destruct, 3416).
--define(wxSplitterWindow_Create, 3417).
--define(wxSplitterWindow_GetMinimumPaneSize, 3418).
--define(wxSplitterWindow_GetSashGravity, 3419).
--define(wxSplitterWindow_GetSashPosition, 3420).
--define(wxSplitterWindow_GetSplitMode, 3421).
--define(wxSplitterWindow_GetWindow1, 3422).
--define(wxSplitterWindow_GetWindow2, 3423).
--define(wxSplitterWindow_Initialize, 3424).
--define(wxSplitterWindow_IsSplit, 3425).
--define(wxSplitterWindow_ReplaceWindow, 3426).
--define(wxSplitterWindow_SetSashGravity, 3427).
--define(wxSplitterWindow_SetSashPosition, 3428).
--define(wxSplitterWindow_SetMinimumPaneSize, 3429).
--define(wxSplitterWindow_SetSplitMode, 3430).
--define(wxSplitterWindow_SplitHorizontally, 3431).
--define(wxSplitterWindow_SplitVertically, 3432).
--define(wxSplitterWindow_Unsplit, 3433).
--define(wxSplitterWindow_UpdateSize, 3434).
--define(wxSplitterEvent_GetSashPosition, 3435).
--define(wxSplitterEvent_GetX, 3436).
--define(wxSplitterEvent_GetY, 3437).
--define(wxSplitterEvent_GetWindowBeingRemoved, 3438).
--define(wxSplitterEvent_SetSashPosition, 3439).
--define(wxHtmlWindow_new_0, 3440).
--define(wxHtmlWindow_new_2, 3441).
--define(wxHtmlWindow_AppendToPage, 3442).
--define(wxHtmlWindow_GetOpenedAnchor, 3443).
--define(wxHtmlWindow_GetOpenedPage, 3444).
--define(wxHtmlWindow_GetOpenedPageTitle, 3445).
--define(wxHtmlWindow_GetRelatedFrame, 3446).
--define(wxHtmlWindow_HistoryBack, 3447).
--define(wxHtmlWindow_HistoryCanBack, 3448).
--define(wxHtmlWindow_HistoryCanForward, 3449).
--define(wxHtmlWindow_HistoryClear, 3450).
--define(wxHtmlWindow_HistoryForward, 3451).
--define(wxHtmlWindow_LoadFile, 3452).
--define(wxHtmlWindow_LoadPage, 3453).
--define(wxHtmlWindow_SelectAll, 3454).
--define(wxHtmlWindow_SelectionToText, 3455).
--define(wxHtmlWindow_SelectLine, 3456).
--define(wxHtmlWindow_SelectWord, 3457).
--define(wxHtmlWindow_SetBorders, 3458).
--define(wxHtmlWindow_SetFonts, 3459).
--define(wxHtmlWindow_SetPage, 3460).
--define(wxHtmlWindow_SetRelatedFrame, 3461).
--define(wxHtmlWindow_SetRelatedStatusBar_1, 3462).
--define(wxHtmlWindow_SetRelatedStatusBar_2, 3463).
--define(wxHtmlWindow_ToText, 3464).
--define(wxHtmlWindow_destroy, 3465).
--define(wxHtmlLinkEvent_GetLinkInfo, 3466).
--define(wxSystemSettings_GetColour, 3467).
--define(wxSystemSettings_GetFont, 3468).
--define(wxSystemSettings_GetMetric, 3469).
--define(wxSystemSettings_GetScreenType, 3470).
--define(wxSystemOptions_GetOption, 3471).
--define(wxSystemOptions_GetOptionInt, 3472).
--define(wxSystemOptions_HasOption, 3473).
--define(wxSystemOptions_IsFalse, 3474).
--define(wxSystemOptions_SetOption_2_1, 3475).
--define(wxSystemOptions_SetOption_2_0, 3476).
--define(wxAuiNotebookEvent_SetSelection, 3477).
--define(wxAuiNotebookEvent_GetSelection, 3478).
--define(wxAuiNotebookEvent_SetOldSelection, 3479).
--define(wxAuiNotebookEvent_GetOldSelection, 3480).
--define(wxAuiNotebookEvent_SetDragSource, 3481).
--define(wxAuiNotebookEvent_GetDragSource, 3482).
--define(wxAuiManagerEvent_SetManager, 3483).
--define(wxAuiManagerEvent_GetManager, 3484).
--define(wxAuiManagerEvent_SetPane, 3485).
--define(wxAuiManagerEvent_GetPane, 3486).
--define(wxAuiManagerEvent_SetButton, 3487).
--define(wxAuiManagerEvent_GetButton, 3488).
--define(wxAuiManagerEvent_SetDC, 3489).
--define(wxAuiManagerEvent_GetDC, 3490).
--define(wxAuiManagerEvent_Veto, 3491).
--define(wxAuiManagerEvent_GetVeto, 3492).
--define(wxAuiManagerEvent_SetCanVeto, 3493).
--define(wxAuiManagerEvent_CanVeto, 3494).
--define(wxLogNull_new, 3495).
--define(wxLogNull_destruct, 3496).
--define(wxTaskBarIcon_new, 3497).
--define(wxTaskBarIcon_destruct, 3498).
--define(wxTaskBarIcon_PopupMenu, 3499).
--define(wxTaskBarIcon_RemoveIcon, 3500).
--define(wxTaskBarIcon_SetIcon, 3501).
--define(wxLocale_new_0, 3502).
--define(wxLocale_new_2_0, 3503).
--define(wxLocale_new_2_1, 3504).
--define(wxLocale_destruct, 3505).
--define(wxLocale_Init_1, 3506).
--define(wxLocale_Init_2, 3507).
--define(wxLocale_AddCatalog_1, 3508).
--define(wxLocale_AddCatalog_2, 3509).
--define(wxLocale_AddCatalog_3, 3510).
--define(wxLocale_AddCatalogLookupPathPrefix, 3511).
--define(wxLocale_GetCanonicalName, 3512).
--define(wxLocale_GetLanguage, 3513).
--define(wxLocale_GetLanguageName, 3514).
--define(wxLocale_GetLocale, 3515).
--define(wxLocale_GetName, 3516).
--define(wxLocale_GetString_2, 3517).
--define(wxLocale_GetString_4, 3518).
--define(wxLocale_GetHeaderValue, 3519).
--define(wxLocale_GetSysName, 3520).
--define(wxLocale_GetSystemEncoding, 3521).
--define(wxLocale_GetSystemEncodingName, 3522).
--define(wxLocale_GetSystemLanguage, 3523).
--define(wxLocale_IsLoaded, 3524).
--define(wxLocale_IsOk, 3525).
--define(wxActivateEvent_GetActive, 3526).
--define(wxPopupWindow_new_0, 3527).
--define(wxPopupWindow_new_2, 3528).
--define(wxPopupWindow_Create, 3529).
--define(wxPopupWindow_Position, 3530).
--define(wxPopupWindow_destroy, 3531).
--define(wxPopupTransientWindow_new_0, 3532).
--define(wxPopupTransientWindow_new_2, 3533).
--define(wxPopupTransientWindow_Popup, 3534).
--define(wxPopupTransientWindow_Dismiss, 3535).
--define(wxPopupTransientWindow_destroy, 3536).
--define(wxOverlay_new, 3537).
--define(wxOverlay_destruct, 3538).
--define(wxOverlay_Reset, 3539).
--define(wxDCOverlay_new_6, 3540).
--define(wxDCOverlay_new_2, 3541).
--define(wxDCOverlay_destruct, 3542).
--define(wxDCOverlay_Clear, 3543).
--define(wxDropFilesEvent_GetPosition, 3544).
--define(wxDropFilesEvent_GetNumberOfFiles, 3545).
--define(wxDropFilesEvent_GetFiles, 3546).
--define(wxDisplay_new_0, 3547).
--define(wxDisplay_new_1_0, 3548).
--define(wxDisplay_new_1_1, 3549).
--define(wxDisplay_destruct, 3550).
--define(wxDisplay_IsOk, 3551).
--define(wxDisplay_GetClientArea, 3552).
--define(wxDisplay_GetGeometry, 3553).
--define(wxDisplay_GetName, 3554).
--define(wxDisplay_IsPrimary, 3555).
--define(wxDisplay_GetCount, 3556).
--define(wxDisplay_GetFromPoint, 3557).
--define(wxDisplay_GetFromWindow, 3558).
--define(wxDisplay_GetPPI, 3559).
--define(wxGCDC_new_1, 3560).
--define(wxGCDC_new_0, 3563).
--define(wxGCDC_destruct, 3564).
--define(wxGCDC_GetGraphicsContext, 3565).
--define(wxGCDC_SetGraphicsContext, 3566).
--define(wxNotificationMessage_new_0, 3567).
--define(wxNotificationMessage_new_2, 3568).
--define(wxNotificationMessage_destruct, 3569).
--define(wxNotificationMessage_AddAction, 3570).
--define(wxNotificationMessage_Close, 3571).
--define(wxNotificationMessage_SetFlags, 3572).
--define(wxNotificationMessage_SetIcon, 3573).
--define(wxNotificationMessage_SetMessage, 3574).
--define(wxNotificationMessage_SetParent, 3575).
--define(wxNotificationMessage_SetTitle, 3576).
--define(wxNotificationMessage_Show, 3577).
--define(wxNotificationMessage_UseTaskBarIcon, 3578).
--define(wxNotificationMessage_MSWUseToasts, 3579).
--define(wxWebView_New, 3581).
--define(wxWebView_GetCurrentTitle, 3582).
--define(wxWebView_GetCurrentURL, 3583).
--define(wxWebView_GetPageSource, 3584).
--define(wxWebView_GetPageText, 3585).
--define(wxWebView_IsBusy, 3586).
--define(wxWebView_IsEditable, 3587).
--define(wxWebView_LoadURL, 3588).
--define(wxWebView_Print, 3589).
--define(wxWebView_Reload, 3590).
--define(wxWebView_RunScript, 3591).
--define(wxWebView_SetEditable, 3592).
--define(wxWebView_SetPage, 3593).
--define(wxWebView_Stop, 3594).
--define(wxWebView_CanCopy, 3595).
--define(wxWebView_CanCut, 3596).
--define(wxWebView_CanPaste, 3597).
--define(wxWebView_Copy, 3598).
--define(wxWebView_Cut, 3599).
--define(wxWebView_Paste, 3600).
--define(wxWebView_EnableContextMenu, 3601).
--define(wxWebView_IsContextMenuEnabled, 3602).
--define(wxWebView_CanGoBack, 3603).
--define(wxWebView_CanGoForward, 3604).
--define(wxWebView_ClearHistory, 3605).
--define(wxWebView_EnableHistory, 3606).
--define(wxWebView_GoBack, 3607).
--define(wxWebView_GoForward, 3608).
--define(wxWebView_ClearSelection, 3609).
--define(wxWebView_DeleteSelection, 3610).
--define(wxWebView_GetSelectedSource, 3611).
--define(wxWebView_GetSelectedText, 3612).
--define(wxWebView_HasSelection, 3613).
--define(wxWebView_SelectAll, 3614).
--define(wxWebView_CanRedo, 3615).
--define(wxWebView_CanUndo, 3616).
--define(wxWebView_Redo, 3617).
--define(wxWebView_Undo, 3618).
--define(wxWebView_Find, 3619).
--define(wxWebView_CanSetZoomType, 3620).
--define(wxWebView_GetZoom, 3621).
--define(wxWebView_GetZoomType, 3622).
--define(wxWebView_SetZoom, 3623).
--define(wxWebView_SetZoomType, 3624).
--define(wxWebView_GetZoomFactor, 3625).
--define(wxWebView_SetZoomFactor, 3626).
--define(wxWebView_IsBackendAvailable, 3627).
--define(wxWebViewEvent_GetString, 3628).
--define(wxWebViewEvent_GetInt, 3629).
--define(wxWebViewEvent_GetTarget, 3630).
--define(wxWebViewEvent_GetURL, 3631).
+-define(wxGLCanvas_CreateSurface, 2495).
+-define(wxGLCanvas_IsDisplaySupported, 2496).
+-define(wxGLCanvas_SwapBuffers, 2497).
+-define(wxGLCanvas_destroy, 2498).
+-define(wxGLContext_new, 2499).
+-define(wxGLContext_SetCurrent, 2500).
+-define(wxGLContext_IsOK, 2501).
+-define(wxGLContext_destroy, 2502).
+-define(wxAuiManager_new, 2503).
+-define(wxAuiManager_destruct, 2504).
+-define(wxAuiManager_AddPane_2_1, 2505).
+-define(wxAuiManager_AddPane_2_0, 2506).
+-define(wxAuiManager_AddPane_3, 2507).
+-define(wxAuiManager_DetachPane, 2508).
+-define(wxAuiManager_GetAllPanes, 2509).
+-define(wxAuiManager_GetArtProvider, 2510).
+-define(wxAuiManager_GetDockSizeConstraint, 2511).
+-define(wxAuiManager_GetFlags, 2512).
+-define(wxAuiManager_GetManagedWindow, 2513).
+-define(wxAuiManager_GetManager, 2514).
+-define(wxAuiManager_GetPane_1_1, 2515).
+-define(wxAuiManager_GetPane_1_0, 2516).
+-define(wxAuiManager_HideHint, 2517).
+-define(wxAuiManager_InsertPane, 2518).
+-define(wxAuiManager_LoadPaneInfo, 2519).
+-define(wxAuiManager_LoadPerspective, 2520).
+-define(wxAuiManager_SavePaneInfo, 2521).
+-define(wxAuiManager_SavePerspective, 2522).
+-define(wxAuiManager_SetArtProvider, 2523).
+-define(wxAuiManager_SetDockSizeConstraint, 2524).
+-define(wxAuiManager_SetFlags, 2525).
+-define(wxAuiManager_SetManagedWindow, 2526).
+-define(wxAuiManager_ShowHint, 2527).
+-define(wxAuiManager_UnInit, 2528).
+-define(wxAuiManager_Update, 2529).
+-define(wxAuiPaneInfo_new_0, 2530).
+-define(wxAuiPaneInfo_new_1, 2531).
+-define(wxAuiPaneInfo_BestSize_1, 2532).
+-define(wxAuiPaneInfo_BestSize_2, 2533).
+-define(wxAuiPaneInfo_Bottom, 2534).
+-define(wxAuiPaneInfo_BottomDockable, 2535).
+-define(wxAuiPaneInfo_Caption, 2536).
+-define(wxAuiPaneInfo_CaptionVisible, 2537).
+-define(wxAuiPaneInfo_Centre, 2538).
+-define(wxAuiPaneInfo_CentrePane, 2539).
+-define(wxAuiPaneInfo_CloseButton, 2540).
+-define(wxAuiPaneInfo_DefaultPane, 2541).
+-define(wxAuiPaneInfo_DestroyOnClose, 2542).
+-define(wxAuiPaneInfo_Direction, 2543).
+-define(wxAuiPaneInfo_Dock, 2544).
+-define(wxAuiPaneInfo_Dockable, 2545).
+-define(wxAuiPaneInfo_Fixed, 2546).
+-define(wxAuiPaneInfo_Float, 2547).
+-define(wxAuiPaneInfo_Floatable, 2548).
+-define(wxAuiPaneInfo_FloatingPosition_1, 2549).
+-define(wxAuiPaneInfo_FloatingPosition_2, 2550).
+-define(wxAuiPaneInfo_FloatingSize_1, 2551).
+-define(wxAuiPaneInfo_FloatingSize_2, 2552).
+-define(wxAuiPaneInfo_Gripper, 2553).
+-define(wxAuiPaneInfo_GripperTop, 2554).
+-define(wxAuiPaneInfo_HasBorder, 2555).
+-define(wxAuiPaneInfo_HasCaption, 2556).
+-define(wxAuiPaneInfo_HasCloseButton, 2557).
+-define(wxAuiPaneInfo_HasFlag, 2558).
+-define(wxAuiPaneInfo_HasGripper, 2559).
+-define(wxAuiPaneInfo_HasGripperTop, 2560).
+-define(wxAuiPaneInfo_HasMaximizeButton, 2561).
+-define(wxAuiPaneInfo_HasMinimizeButton, 2562).
+-define(wxAuiPaneInfo_HasPinButton, 2563).
+-define(wxAuiPaneInfo_Hide, 2564).
+-define(wxAuiPaneInfo_IsBottomDockable, 2565).
+-define(wxAuiPaneInfo_IsDocked, 2566).
+-define(wxAuiPaneInfo_IsFixed, 2567).
+-define(wxAuiPaneInfo_IsFloatable, 2568).
+-define(wxAuiPaneInfo_IsFloating, 2569).
+-define(wxAuiPaneInfo_IsLeftDockable, 2570).
+-define(wxAuiPaneInfo_IsMovable, 2571).
+-define(wxAuiPaneInfo_IsOk, 2572).
+-define(wxAuiPaneInfo_IsResizable, 2573).
+-define(wxAuiPaneInfo_IsRightDockable, 2574).
+-define(wxAuiPaneInfo_IsShown, 2575).
+-define(wxAuiPaneInfo_IsToolbar, 2576).
+-define(wxAuiPaneInfo_IsTopDockable, 2577).
+-define(wxAuiPaneInfo_Layer, 2578).
+-define(wxAuiPaneInfo_Left, 2579).
+-define(wxAuiPaneInfo_LeftDockable, 2580).
+-define(wxAuiPaneInfo_MaxSize_1, 2581).
+-define(wxAuiPaneInfo_MaxSize_2, 2582).
+-define(wxAuiPaneInfo_MaximizeButton, 2583).
+-define(wxAuiPaneInfo_MinSize_1, 2584).
+-define(wxAuiPaneInfo_MinSize_2, 2585).
+-define(wxAuiPaneInfo_MinimizeButton, 2586).
+-define(wxAuiPaneInfo_Movable, 2587).
+-define(wxAuiPaneInfo_Name, 2588).
+-define(wxAuiPaneInfo_PaneBorder, 2589).
+-define(wxAuiPaneInfo_PinButton, 2590).
+-define(wxAuiPaneInfo_Position, 2591).
+-define(wxAuiPaneInfo_Resizable, 2592).
+-define(wxAuiPaneInfo_Right, 2593).
+-define(wxAuiPaneInfo_RightDockable, 2594).
+-define(wxAuiPaneInfo_Row, 2595).
+-define(wxAuiPaneInfo_SafeSet, 2596).
+-define(wxAuiPaneInfo_SetFlag, 2597).
+-define(wxAuiPaneInfo_Show, 2598).
+-define(wxAuiPaneInfo_ToolbarPane, 2599).
+-define(wxAuiPaneInfo_Top, 2600).
+-define(wxAuiPaneInfo_TopDockable, 2601).
+-define(wxAuiPaneInfo_Window, 2602).
+-define(wxAuiPaneInfo_GetWindow, 2603).
+-define(wxAuiPaneInfo_GetFrame, 2604).
+-define(wxAuiPaneInfo_GetDirection, 2605).
+-define(wxAuiPaneInfo_GetLayer, 2606).
+-define(wxAuiPaneInfo_GetRow, 2607).
+-define(wxAuiPaneInfo_GetPosition, 2608).
+-define(wxAuiPaneInfo_GetFloatingPosition, 2609).
+-define(wxAuiPaneInfo_GetFloatingSize, 2610).
+-define(wxAuiPaneInfo_destroy, 2611).
+-define(wxAuiNotebook_new_0, 2612).
+-define(wxAuiNotebook_new_2, 2613).
+-define(wxAuiNotebook_AddPage_3, 2614).
+-define(wxAuiNotebook_AddPage_4, 2615).
+-define(wxAuiNotebook_Create_2, 2616).
+-define(wxAuiNotebook_Create_3, 2617).
+-define(wxAuiNotebook_DeletePage, 2618).
+-define(wxAuiNotebook_GetArtProvider, 2619).
+-define(wxAuiNotebook_GetPage, 2620).
+-define(wxAuiNotebook_GetPageBitmap, 2621).
+-define(wxAuiNotebook_GetPageCount, 2622).
+-define(wxAuiNotebook_GetPageIndex, 2623).
+-define(wxAuiNotebook_GetPageText, 2624).
+-define(wxAuiNotebook_GetSelection, 2625).
+-define(wxAuiNotebook_InsertPage_4, 2626).
+-define(wxAuiNotebook_InsertPage_5, 2627).
+-define(wxAuiNotebook_RemovePage, 2628).
+-define(wxAuiNotebook_SetArtProvider, 2629).
+-define(wxAuiNotebook_SetFont, 2630).
+-define(wxAuiNotebook_SetPageBitmap, 2631).
+-define(wxAuiNotebook_SetPageText, 2632).
+-define(wxAuiNotebook_SetSelection, 2633).
+-define(wxAuiNotebook_SetTabCtrlHeight, 2634).
+-define(wxAuiNotebook_SetUniformBitmapSize, 2635).
+-define(wxAuiNotebook_destroy, 2636).
+-define(wxAuiTabArt_SetFlags, 2637).
+-define(wxAuiTabArt_SetMeasuringFont, 2638).
+-define(wxAuiTabArt_SetNormalFont, 2639).
+-define(wxAuiTabArt_SetSelectedFont, 2640).
+-define(wxAuiTabArt_SetColour, 2641).
+-define(wxAuiTabArt_SetActiveColour, 2642).
+-define(wxAuiDockArt_GetColour, 2643).
+-define(wxAuiDockArt_GetFont, 2644).
+-define(wxAuiDockArt_GetMetric, 2645).
+-define(wxAuiDockArt_SetColour, 2646).
+-define(wxAuiDockArt_SetFont, 2647).
+-define(wxAuiDockArt_SetMetric, 2648).
+-define(wxAuiSimpleTabArt_new, 2649).
+-define(wxAuiSimpleTabArt_destroy, 2650).
+-define(wxMDIParentFrame_new_0, 2651).
+-define(wxMDIParentFrame_new_4, 2652).
+-define(wxMDIParentFrame_destruct, 2653).
+-define(wxMDIParentFrame_ActivateNext, 2654).
+-define(wxMDIParentFrame_ActivatePrevious, 2655).
+-define(wxMDIParentFrame_ArrangeIcons, 2656).
+-define(wxMDIParentFrame_Cascade, 2657).
+-define(wxMDIParentFrame_Create, 2658).
+-define(wxMDIParentFrame_GetActiveChild, 2659).
+-define(wxMDIParentFrame_GetClientWindow, 2660).
+-define(wxMDIParentFrame_Tile, 2661).
+-define(wxMDIChildFrame_new_0, 2662).
+-define(wxMDIChildFrame_new_4, 2663).
+-define(wxMDIChildFrame_destruct, 2664).
+-define(wxMDIChildFrame_Activate, 2665).
+-define(wxMDIChildFrame_Create, 2666).
+-define(wxMDIChildFrame_Maximize, 2667).
+-define(wxMDIChildFrame_Restore, 2668).
+-define(wxMDIClientWindow_new, 2669).
+-define(wxMDIClientWindow_CreateClient, 2670).
+-define(wxMDIClientWindow_destroy, 2671).
+-define(wxLayoutAlgorithm_new, 2672).
+-define(wxLayoutAlgorithm_destruct, 2673).
+-define(wxLayoutAlgorithm_LayoutFrame, 2674).
+-define(wxLayoutAlgorithm_LayoutMDIFrame, 2675).
+-define(wxLayoutAlgorithm_LayoutWindow, 2676).
+-define(wxEvent_GetId, 2677).
+-define(wxEvent_GetSkipped, 2678).
+-define(wxEvent_GetTimestamp, 2679).
+-define(wxEvent_IsCommandEvent, 2680).
+-define(wxEvent_ResumePropagation, 2681).
+-define(wxEvent_ShouldPropagate, 2682).
+-define(wxEvent_Skip, 2683).
+-define(wxEvent_StopPropagation, 2684).
+-define(wxCommandEvent_getClientData, 2685).
+-define(wxCommandEvent_GetExtraLong, 2686).
+-define(wxCommandEvent_GetInt, 2687).
+-define(wxCommandEvent_GetSelection, 2688).
+-define(wxCommandEvent_GetString, 2689).
+-define(wxCommandEvent_IsChecked, 2690).
+-define(wxCommandEvent_IsSelection, 2691).
+-define(wxCommandEvent_SetInt, 2692).
+-define(wxCommandEvent_SetString, 2693).
+-define(wxScrollEvent_GetOrientation, 2694).
+-define(wxScrollEvent_GetPosition, 2695).
+-define(wxScrollWinEvent_GetOrientation, 2696).
+-define(wxScrollWinEvent_GetPosition, 2697).
+-define(wxMouseEvent_AltDown, 2698).
+-define(wxMouseEvent_Button, 2699).
+-define(wxMouseEvent_ButtonDClick, 2700).
+-define(wxMouseEvent_ButtonDown, 2701).
+-define(wxMouseEvent_ButtonUp, 2702).
+-define(wxMouseEvent_CmdDown, 2703).
+-define(wxMouseEvent_ControlDown, 2704).
+-define(wxMouseEvent_Dragging, 2705).
+-define(wxMouseEvent_Entering, 2706).
+-define(wxMouseEvent_GetButton, 2707).
+-define(wxMouseEvent_GetPosition, 2708).
+-define(wxMouseEvent_GetLogicalPosition, 2710).
+-define(wxMouseEvent_GetLinesPerAction, 2711).
+-define(wxMouseEvent_GetWheelRotation, 2712).
+-define(wxMouseEvent_GetWheelDelta, 2713).
+-define(wxMouseEvent_GetX, 2714).
+-define(wxMouseEvent_GetY, 2715).
+-define(wxMouseEvent_IsButton, 2716).
+-define(wxMouseEvent_IsPageScroll, 2717).
+-define(wxMouseEvent_Leaving, 2718).
+-define(wxMouseEvent_LeftDClick, 2719).
+-define(wxMouseEvent_LeftDown, 2720).
+-define(wxMouseEvent_LeftIsDown, 2721).
+-define(wxMouseEvent_LeftUp, 2722).
+-define(wxMouseEvent_MetaDown, 2723).
+-define(wxMouseEvent_MiddleDClick, 2724).
+-define(wxMouseEvent_MiddleDown, 2725).
+-define(wxMouseEvent_MiddleIsDown, 2726).
+-define(wxMouseEvent_MiddleUp, 2727).
+-define(wxMouseEvent_Moving, 2728).
+-define(wxMouseEvent_RightDClick, 2729).
+-define(wxMouseEvent_RightDown, 2730).
+-define(wxMouseEvent_RightIsDown, 2731).
+-define(wxMouseEvent_RightUp, 2732).
+-define(wxMouseEvent_ShiftDown, 2733).
+-define(wxMouseEvent_GetWheelAxis, 2734).
+-define(wxMouseEvent_Aux1DClick, 2735).
+-define(wxMouseEvent_Aux1Down, 2736).
+-define(wxMouseEvent_Aux1Up, 2737).
+-define(wxMouseEvent_Aux2DClick, 2738).
+-define(wxMouseEvent_Aux2Down, 2739).
+-define(wxMouseEvent_Aux2Up, 2740).
+-define(wxSetCursorEvent_GetCursor, 2741).
+-define(wxSetCursorEvent_GetX, 2742).
+-define(wxSetCursorEvent_GetY, 2743).
+-define(wxSetCursorEvent_HasCursor, 2744).
+-define(wxSetCursorEvent_SetCursor, 2745).
+-define(wxKeyEvent_AltDown, 2746).
+-define(wxKeyEvent_CmdDown, 2747).
+-define(wxKeyEvent_ControlDown, 2748).
+-define(wxKeyEvent_GetKeyCode, 2749).
+-define(wxKeyEvent_GetModifiers, 2750).
+-define(wxKeyEvent_GetPosition, 2751).
+-define(wxKeyEvent_GetRawKeyCode, 2753).
+-define(wxKeyEvent_GetRawKeyFlags, 2754).
+-define(wxKeyEvent_GetUnicodeKey, 2755).
+-define(wxKeyEvent_GetX, 2756).
+-define(wxKeyEvent_GetY, 2757).
+-define(wxKeyEvent_HasModifiers, 2758).
+-define(wxKeyEvent_MetaDown, 2759).
+-define(wxKeyEvent_ShiftDown, 2760).
+-define(wxSizeEvent_GetSize, 2761).
+-define(wxSizeEvent_GetRect, 2762).
+-define(wxMoveEvent_GetPosition, 2763).
+-define(wxMoveEvent_GetRect, 2764).
+-define(wxEraseEvent_GetDC, 2765).
+-define(wxFocusEvent_GetWindow, 2766).
+-define(wxChildFocusEvent_GetWindow, 2767).
+-define(wxMenuEvent_GetMenu, 2768).
+-define(wxMenuEvent_GetMenuId, 2769).
+-define(wxMenuEvent_IsPopup, 2770).
+-define(wxCloseEvent_CanVeto, 2771).
+-define(wxCloseEvent_GetLoggingOff, 2772).
+-define(wxCloseEvent_SetCanVeto, 2773).
+-define(wxCloseEvent_SetLoggingOff, 2774).
+-define(wxCloseEvent_Veto, 2775).
+-define(wxShowEvent_SetShow, 2776).
+-define(wxShowEvent_IsShown, 2777).
+-define(wxIconizeEvent_IsIconized, 2778).
+-define(wxJoystickEvent_ButtonDown, 2779).
+-define(wxJoystickEvent_ButtonIsDown, 2780).
+-define(wxJoystickEvent_ButtonUp, 2781).
+-define(wxJoystickEvent_GetButtonChange, 2782).
+-define(wxJoystickEvent_GetButtonState, 2783).
+-define(wxJoystickEvent_GetJoystick, 2784).
+-define(wxJoystickEvent_GetPosition, 2785).
+-define(wxJoystickEvent_GetZPosition, 2786).
+-define(wxJoystickEvent_IsButton, 2787).
+-define(wxJoystickEvent_IsMove, 2788).
+-define(wxJoystickEvent_IsZMove, 2789).
+-define(wxUpdateUIEvent_CanUpdate, 2790).
+-define(wxUpdateUIEvent_Check, 2791).
+-define(wxUpdateUIEvent_Enable, 2792).
+-define(wxUpdateUIEvent_Show, 2793).
+-define(wxUpdateUIEvent_GetChecked, 2794).
+-define(wxUpdateUIEvent_GetEnabled, 2795).
+-define(wxUpdateUIEvent_GetShown, 2796).
+-define(wxUpdateUIEvent_GetSetChecked, 2797).
+-define(wxUpdateUIEvent_GetSetEnabled, 2798).
+-define(wxUpdateUIEvent_GetSetShown, 2799).
+-define(wxUpdateUIEvent_GetSetText, 2800).
+-define(wxUpdateUIEvent_GetText, 2801).
+-define(wxUpdateUIEvent_GetMode, 2802).
+-define(wxUpdateUIEvent_GetUpdateInterval, 2803).
+-define(wxUpdateUIEvent_ResetUpdateTime, 2804).
+-define(wxUpdateUIEvent_SetMode, 2805).
+-define(wxUpdateUIEvent_SetText, 2806).
+-define(wxUpdateUIEvent_SetUpdateInterval, 2807).
+-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2808).
+-define(wxPaletteChangedEvent_SetChangedWindow, 2809).
+-define(wxPaletteChangedEvent_GetChangedWindow, 2810).
+-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2811).
+-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2812).
+-define(wxNavigationKeyEvent_GetDirection, 2813).
+-define(wxNavigationKeyEvent_SetDirection, 2814).
+-define(wxNavigationKeyEvent_IsWindowChange, 2815).
+-define(wxNavigationKeyEvent_SetWindowChange, 2816).
+-define(wxNavigationKeyEvent_IsFromTab, 2817).
+-define(wxNavigationKeyEvent_SetFromTab, 2818).
+-define(wxNavigationKeyEvent_GetCurrentFocus, 2819).
+-define(wxNavigationKeyEvent_SetCurrentFocus, 2820).
+-define(wxHelpEvent_GetOrigin, 2821).
+-define(wxHelpEvent_GetPosition, 2822).
+-define(wxHelpEvent_SetOrigin, 2823).
+-define(wxHelpEvent_SetPosition, 2824).
+-define(wxContextMenuEvent_GetPosition, 2825).
+-define(wxContextMenuEvent_SetPosition, 2826).
+-define(wxIdleEvent_GetMode, 2827).
+-define(wxIdleEvent_RequestMore, 2828).
+-define(wxIdleEvent_MoreRequested, 2829).
+-define(wxIdleEvent_SetMode, 2830).
+-define(wxGridEvent_AltDown, 2831).
+-define(wxGridEvent_ControlDown, 2832).
+-define(wxGridEvent_GetCol, 2833).
+-define(wxGridEvent_GetPosition, 2834).
+-define(wxGridEvent_GetRow, 2835).
+-define(wxGridEvent_MetaDown, 2836).
+-define(wxGridEvent_Selecting, 2837).
+-define(wxGridEvent_ShiftDown, 2838).
+-define(wxNotifyEvent_Allow, 2839).
+-define(wxNotifyEvent_IsAllowed, 2840).
+-define(wxNotifyEvent_Veto, 2841).
+-define(wxSashEvent_GetEdge, 2842).
+-define(wxSashEvent_GetDragRect, 2843).
+-define(wxSashEvent_GetDragStatus, 2844).
+-define(wxListEvent_GetCacheFrom, 2845).
+-define(wxListEvent_GetCacheTo, 2846).
+-define(wxListEvent_GetKeyCode, 2847).
+-define(wxListEvent_GetIndex, 2848).
+-define(wxListEvent_GetColumn, 2849).
+-define(wxListEvent_GetPoint, 2850).
+-define(wxListEvent_GetLabel, 2851).
+-define(wxListEvent_GetText, 2852).
+-define(wxListEvent_GetImage, 2853).
+-define(wxListEvent_GetData, 2854).
+-define(wxListEvent_GetMask, 2855).
+-define(wxListEvent_GetItem, 2856).
+-define(wxListEvent_IsEditCancelled, 2857).
+-define(wxDateEvent_GetDate, 2858).
+-define(wxCalendarEvent_GetWeekDay, 2859).
+-define(wxCalendarEvent_GetDate, 2860).
+-define(wxFileDirPickerEvent_GetPath, 2861).
+-define(wxColourPickerEvent_GetColour, 2862).
+-define(wxFontPickerEvent_GetFont, 2863).
+-define(wxStyledTextEvent_GetPosition, 2864).
+-define(wxStyledTextEvent_GetKey, 2865).
+-define(wxStyledTextEvent_GetModifiers, 2866).
+-define(wxStyledTextEvent_GetModificationType, 2867).
+-define(wxStyledTextEvent_GetText, 2868).
+-define(wxStyledTextEvent_GetLength, 2869).
+-define(wxStyledTextEvent_GetLinesAdded, 2870).
+-define(wxStyledTextEvent_GetLine, 2871).
+-define(wxStyledTextEvent_GetFoldLevelNow, 2872).
+-define(wxStyledTextEvent_GetFoldLevelPrev, 2873).
+-define(wxStyledTextEvent_GetMargin, 2874).
+-define(wxStyledTextEvent_GetMessage, 2875).
+-define(wxStyledTextEvent_GetWParam, 2876).
+-define(wxStyledTextEvent_GetLParam, 2877).
+-define(wxStyledTextEvent_GetListType, 2878).
+-define(wxStyledTextEvent_GetX, 2879).
+-define(wxStyledTextEvent_GetY, 2880).
+-define(wxStyledTextEvent_GetDragText, 2881).
+-define(wxStyledTextEvent_GetDragAllowMove, 2882).
+-define(wxStyledTextEvent_GetDragResult, 2883).
+-define(wxStyledTextEvent_GetShift, 2884).
+-define(wxStyledTextEvent_GetControl, 2885).
+-define(wxStyledTextEvent_GetAlt, 2886).
+-define(utils_wxGetKeyState, 2887).
+-define(utils_wxGetMousePosition, 2888).
+-define(utils_wxGetMouseState, 2889).
+-define(utils_wxSetDetectableAutoRepeat, 2890).
+-define(utils_wxBell, 2891).
+-define(utils_wxFindMenuItemId, 2892).
+-define(utils_wxFindWindowAtPoint, 2893).
+-define(utils_wxBeginBusyCursor, 2894).
+-define(utils_wxEndBusyCursor, 2895).
+-define(utils_wxIsBusy, 2896).
+-define(utils_wxShutdown, 2897).
+-define(utils_wxShell, 2898).
+-define(utils_wxLaunchDefaultBrowser, 2899).
+-define(utils_wxGetEmailAddress, 2900).
+-define(utils_wxGetUserId, 2901).
+-define(utils_wxGetHomeDir, 2902).
+-define(utils_wxNewId, 2903).
+-define(utils_wxRegisterId, 2904).
+-define(utils_wxGetCurrentId, 2905).
+-define(utils_wxGetOsDescription, 2906).
+-define(utils_wxIsPlatformLittleEndian, 2907).
+-define(utils_wxIsPlatform64Bit, 2908).
+-define(gdicmn_wxDisplaySize, 2909).
+-define(gdicmn_wxSetCursor, 2910).
+-define(wxPrintout_new, 2911).
+-define(wxPrintout_destruct, 2912).
+-define(wxPrintout_GetDC, 2913).
+-define(wxPrintout_GetPageSizeMM, 2914).
+-define(wxPrintout_GetPageSizePixels, 2915).
+-define(wxPrintout_GetPaperRectPixels, 2916).
+-define(wxPrintout_GetPPIPrinter, 2917).
+-define(wxPrintout_GetPPIScreen, 2918).
+-define(wxPrintout_GetTitle, 2919).
+-define(wxPrintout_IsPreview, 2920).
+-define(wxPrintout_FitThisSizeToPaper, 2921).
+-define(wxPrintout_FitThisSizeToPage, 2922).
+-define(wxPrintout_FitThisSizeToPageMargins, 2923).
+-define(wxPrintout_MapScreenSizeToPaper, 2924).
+-define(wxPrintout_MapScreenSizeToPage, 2925).
+-define(wxPrintout_MapScreenSizeToPageMargins, 2926).
+-define(wxPrintout_MapScreenSizeToDevice, 2927).
+-define(wxPrintout_GetLogicalPaperRect, 2928).
+-define(wxPrintout_GetLogicalPageRect, 2929).
+-define(wxPrintout_GetLogicalPageMarginsRect, 2930).
+-define(wxPrintout_SetLogicalOrigin, 2931).
+-define(wxPrintout_OffsetLogicalOrigin, 2932).
+-define(wxStyledTextCtrl_new_2, 2933).
+-define(wxStyledTextCtrl_new_0, 2934).
+-define(wxStyledTextCtrl_destruct, 2935).
+-define(wxStyledTextCtrl_Create, 2936).
+-define(wxStyledTextCtrl_AddText, 2937).
+-define(wxStyledTextCtrl_InsertText, 2938).
+-define(wxStyledTextCtrl_ClearAll, 2939).
+-define(wxStyledTextCtrl_ClearDocumentStyle, 2940).
+-define(wxStyledTextCtrl_GetLength, 2941).
+-define(wxStyledTextCtrl_GetCharAt, 2942).
+-define(wxStyledTextCtrl_GetCurrentPos, 2943).
+-define(wxStyledTextCtrl_GetAnchor, 2944).
+-define(wxStyledTextCtrl_GetStyleAt, 2945).
+-define(wxStyledTextCtrl_Redo, 2946).
+-define(wxStyledTextCtrl_SetUndoCollection, 2947).
+-define(wxStyledTextCtrl_SelectAll, 2948).
+-define(wxStyledTextCtrl_SetSavePoint, 2949).
+-define(wxStyledTextCtrl_CanRedo, 2950).
+-define(wxStyledTextCtrl_MarkerLineFromHandle, 2951).
+-define(wxStyledTextCtrl_MarkerDeleteHandle, 2952).
+-define(wxStyledTextCtrl_GetUndoCollection, 2953).
+-define(wxStyledTextCtrl_GetViewWhiteSpace, 2954).
+-define(wxStyledTextCtrl_SetViewWhiteSpace, 2955).
+-define(wxStyledTextCtrl_PositionFromPoint, 2956).
+-define(wxStyledTextCtrl_PositionFromPointClose, 2957).
+-define(wxStyledTextCtrl_GotoLine, 2958).
+-define(wxStyledTextCtrl_GotoPos, 2959).
+-define(wxStyledTextCtrl_SetAnchor, 2960).
+-define(wxStyledTextCtrl_GetCurLine, 2961).
+-define(wxStyledTextCtrl_GetEndStyled, 2962).
+-define(wxStyledTextCtrl_ConvertEOLs, 2963).
+-define(wxStyledTextCtrl_GetEOLMode, 2964).
+-define(wxStyledTextCtrl_SetEOLMode, 2965).
+-define(wxStyledTextCtrl_StartStyling, 2966).
+-define(wxStyledTextCtrl_SetStyling, 2967).
+-define(wxStyledTextCtrl_GetBufferedDraw, 2968).
+-define(wxStyledTextCtrl_SetBufferedDraw, 2969).
+-define(wxStyledTextCtrl_SetTabWidth, 2970).
+-define(wxStyledTextCtrl_GetTabWidth, 2971).
+-define(wxStyledTextCtrl_SetCodePage, 2972).
+-define(wxStyledTextCtrl_MarkerDefine, 2973).
+-define(wxStyledTextCtrl_MarkerSetForeground, 2974).
+-define(wxStyledTextCtrl_MarkerSetBackground, 2975).
+-define(wxStyledTextCtrl_MarkerAdd, 2976).
+-define(wxStyledTextCtrl_MarkerDelete, 2977).
+-define(wxStyledTextCtrl_MarkerDeleteAll, 2978).
+-define(wxStyledTextCtrl_MarkerGet, 2979).
+-define(wxStyledTextCtrl_MarkerNext, 2980).
+-define(wxStyledTextCtrl_MarkerPrevious, 2981).
+-define(wxStyledTextCtrl_MarkerDefineBitmap, 2982).
+-define(wxStyledTextCtrl_MarkerAddSet, 2983).
+-define(wxStyledTextCtrl_MarkerSetAlpha, 2984).
+-define(wxStyledTextCtrl_SetMarginType, 2985).
+-define(wxStyledTextCtrl_GetMarginType, 2986).
+-define(wxStyledTextCtrl_SetMarginWidth, 2987).
+-define(wxStyledTextCtrl_GetMarginWidth, 2988).
+-define(wxStyledTextCtrl_SetMarginMask, 2989).
+-define(wxStyledTextCtrl_GetMarginMask, 2990).
+-define(wxStyledTextCtrl_SetMarginSensitive, 2991).
+-define(wxStyledTextCtrl_GetMarginSensitive, 2992).
+-define(wxStyledTextCtrl_StyleClearAll, 2993).
+-define(wxStyledTextCtrl_StyleSetForeground, 2994).
+-define(wxStyledTextCtrl_StyleSetBackground, 2995).
+-define(wxStyledTextCtrl_StyleSetBold, 2996).
+-define(wxStyledTextCtrl_StyleSetItalic, 2997).
+-define(wxStyledTextCtrl_StyleSetSize, 2998).
+-define(wxStyledTextCtrl_StyleSetFaceName, 2999).
+-define(wxStyledTextCtrl_StyleSetEOLFilled, 3000).
+-define(wxStyledTextCtrl_StyleResetDefault, 3001).
+-define(wxStyledTextCtrl_StyleSetUnderline, 3002).
+-define(wxStyledTextCtrl_StyleSetCase, 3003).
+-define(wxStyledTextCtrl_StyleSetHotSpot, 3004).
+-define(wxStyledTextCtrl_SetSelForeground, 3005).
+-define(wxStyledTextCtrl_SetSelBackground, 3006).
+-define(wxStyledTextCtrl_GetSelAlpha, 3007).
+-define(wxStyledTextCtrl_SetSelAlpha, 3008).
+-define(wxStyledTextCtrl_SetCaretForeground, 3009).
+-define(wxStyledTextCtrl_CmdKeyAssign, 3010).
+-define(wxStyledTextCtrl_CmdKeyClear, 3011).
+-define(wxStyledTextCtrl_CmdKeyClearAll, 3012).
+-define(wxStyledTextCtrl_SetStyleBytes, 3013).
+-define(wxStyledTextCtrl_StyleSetVisible, 3014).
+-define(wxStyledTextCtrl_GetCaretPeriod, 3015).
+-define(wxStyledTextCtrl_SetCaretPeriod, 3016).
+-define(wxStyledTextCtrl_SetWordChars, 3017).
+-define(wxStyledTextCtrl_BeginUndoAction, 3018).
+-define(wxStyledTextCtrl_EndUndoAction, 3019).
+-define(wxStyledTextCtrl_IndicatorSetStyle, 3020).
+-define(wxStyledTextCtrl_IndicatorGetStyle, 3021).
+-define(wxStyledTextCtrl_IndicatorSetForeground, 3022).
+-define(wxStyledTextCtrl_IndicatorGetForeground, 3023).
+-define(wxStyledTextCtrl_SetWhitespaceForeground, 3024).
+-define(wxStyledTextCtrl_SetWhitespaceBackground, 3025).
+-define(wxStyledTextCtrl_GetStyleBits, 3026).
+-define(wxStyledTextCtrl_SetLineState, 3027).
+-define(wxStyledTextCtrl_GetLineState, 3028).
+-define(wxStyledTextCtrl_GetMaxLineState, 3029).
+-define(wxStyledTextCtrl_GetCaretLineVisible, 3030).
+-define(wxStyledTextCtrl_SetCaretLineVisible, 3031).
+-define(wxStyledTextCtrl_GetCaretLineBackground, 3032).
+-define(wxStyledTextCtrl_SetCaretLineBackground, 3033).
+-define(wxStyledTextCtrl_AutoCompShow, 3034).
+-define(wxStyledTextCtrl_AutoCompCancel, 3035).
+-define(wxStyledTextCtrl_AutoCompActive, 3036).
+-define(wxStyledTextCtrl_AutoCompPosStart, 3037).
+-define(wxStyledTextCtrl_AutoCompComplete, 3038).
+-define(wxStyledTextCtrl_AutoCompStops, 3039).
+-define(wxStyledTextCtrl_AutoCompSetSeparator, 3040).
+-define(wxStyledTextCtrl_AutoCompGetSeparator, 3041).
+-define(wxStyledTextCtrl_AutoCompSelect, 3042).
+-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3043).
+-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3044).
+-define(wxStyledTextCtrl_AutoCompSetFillUps, 3045).
+-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3046).
+-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3047).
+-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3048).
+-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3049).
+-define(wxStyledTextCtrl_UserListShow, 3050).
+-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3051).
+-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3052).
+-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3053).
+-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3054).
+-define(wxStyledTextCtrl_RegisterImage, 3055).
+-define(wxStyledTextCtrl_ClearRegisteredImages, 3056).
+-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3057).
+-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3058).
+-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3059).
+-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3060).
+-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3061).
+-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3062).
+-define(wxStyledTextCtrl_SetIndent, 3063).
+-define(wxStyledTextCtrl_GetIndent, 3064).
+-define(wxStyledTextCtrl_SetUseTabs, 3065).
+-define(wxStyledTextCtrl_GetUseTabs, 3066).
+-define(wxStyledTextCtrl_SetLineIndentation, 3067).
+-define(wxStyledTextCtrl_GetLineIndentation, 3068).
+-define(wxStyledTextCtrl_GetLineIndentPosition, 3069).
+-define(wxStyledTextCtrl_GetColumn, 3070).
+-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3071).
+-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3072).
+-define(wxStyledTextCtrl_SetIndentationGuides, 3073).
+-define(wxStyledTextCtrl_GetIndentationGuides, 3074).
+-define(wxStyledTextCtrl_SetHighlightGuide, 3075).
+-define(wxStyledTextCtrl_GetHighlightGuide, 3076).
+-define(wxStyledTextCtrl_GetLineEndPosition, 3077).
+-define(wxStyledTextCtrl_GetCodePage, 3078).
+-define(wxStyledTextCtrl_GetCaretForeground, 3079).
+-define(wxStyledTextCtrl_GetReadOnly, 3080).
+-define(wxStyledTextCtrl_SetCurrentPos, 3081).
+-define(wxStyledTextCtrl_SetSelectionStart, 3082).
+-define(wxStyledTextCtrl_GetSelectionStart, 3083).
+-define(wxStyledTextCtrl_SetSelectionEnd, 3084).
+-define(wxStyledTextCtrl_GetSelectionEnd, 3085).
+-define(wxStyledTextCtrl_SetPrintMagnification, 3086).
+-define(wxStyledTextCtrl_GetPrintMagnification, 3087).
+-define(wxStyledTextCtrl_SetPrintColourMode, 3088).
+-define(wxStyledTextCtrl_GetPrintColourMode, 3089).
+-define(wxStyledTextCtrl_FindText, 3090).
+-define(wxStyledTextCtrl_FormatRange, 3091).
+-define(wxStyledTextCtrl_GetFirstVisibleLine, 3092).
+-define(wxStyledTextCtrl_GetLine, 3093).
+-define(wxStyledTextCtrl_GetLineCount, 3094).
+-define(wxStyledTextCtrl_SetMarginLeft, 3095).
+-define(wxStyledTextCtrl_GetMarginLeft, 3096).
+-define(wxStyledTextCtrl_SetMarginRight, 3097).
+-define(wxStyledTextCtrl_GetMarginRight, 3098).
+-define(wxStyledTextCtrl_GetModify, 3099).
+-define(wxStyledTextCtrl_SetSelection, 3100).
+-define(wxStyledTextCtrl_GetSelectedText, 3101).
+-define(wxStyledTextCtrl_GetTextRange, 3102).
+-define(wxStyledTextCtrl_HideSelection, 3103).
+-define(wxStyledTextCtrl_LineFromPosition, 3104).
+-define(wxStyledTextCtrl_PositionFromLine, 3105).
+-define(wxStyledTextCtrl_LineScroll, 3106).
+-define(wxStyledTextCtrl_EnsureCaretVisible, 3107).
+-define(wxStyledTextCtrl_ReplaceSelection, 3108).
+-define(wxStyledTextCtrl_SetReadOnly, 3109).
+-define(wxStyledTextCtrl_CanPaste, 3110).
+-define(wxStyledTextCtrl_CanUndo, 3111).
+-define(wxStyledTextCtrl_EmptyUndoBuffer, 3112).
+-define(wxStyledTextCtrl_Undo, 3113).
+-define(wxStyledTextCtrl_Cut, 3114).
+-define(wxStyledTextCtrl_Copy, 3115).
+-define(wxStyledTextCtrl_Paste, 3116).
+-define(wxStyledTextCtrl_Clear, 3117).
+-define(wxStyledTextCtrl_SetText, 3118).
+-define(wxStyledTextCtrl_GetText, 3119).
+-define(wxStyledTextCtrl_GetTextLength, 3120).
+-define(wxStyledTextCtrl_GetOvertype, 3121).
+-define(wxStyledTextCtrl_SetCaretWidth, 3122).
+-define(wxStyledTextCtrl_GetCaretWidth, 3123).
+-define(wxStyledTextCtrl_SetTargetStart, 3124).
+-define(wxStyledTextCtrl_GetTargetStart, 3125).
+-define(wxStyledTextCtrl_SetTargetEnd, 3126).
+-define(wxStyledTextCtrl_GetTargetEnd, 3127).
+-define(wxStyledTextCtrl_ReplaceTarget, 3128).
+-define(wxStyledTextCtrl_SearchInTarget, 3129).
+-define(wxStyledTextCtrl_SetSearchFlags, 3130).
+-define(wxStyledTextCtrl_GetSearchFlags, 3131).
+-define(wxStyledTextCtrl_CallTipShow, 3132).
+-define(wxStyledTextCtrl_CallTipCancel, 3133).
+-define(wxStyledTextCtrl_CallTipActive, 3134).
+-define(wxStyledTextCtrl_CallTipPosAtStart, 3135).
+-define(wxStyledTextCtrl_CallTipSetHighlight, 3136).
+-define(wxStyledTextCtrl_CallTipSetBackground, 3137).
+-define(wxStyledTextCtrl_CallTipSetForeground, 3138).
+-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3139).
+-define(wxStyledTextCtrl_CallTipUseStyle, 3140).
+-define(wxStyledTextCtrl_VisibleFromDocLine, 3141).
+-define(wxStyledTextCtrl_DocLineFromVisible, 3142).
+-define(wxStyledTextCtrl_WrapCount, 3143).
+-define(wxStyledTextCtrl_SetFoldLevel, 3144).
+-define(wxStyledTextCtrl_GetFoldLevel, 3145).
+-define(wxStyledTextCtrl_GetLastChild, 3146).
+-define(wxStyledTextCtrl_GetFoldParent, 3147).
+-define(wxStyledTextCtrl_ShowLines, 3148).
+-define(wxStyledTextCtrl_HideLines, 3149).
+-define(wxStyledTextCtrl_GetLineVisible, 3150).
+-define(wxStyledTextCtrl_SetFoldExpanded, 3151).
+-define(wxStyledTextCtrl_GetFoldExpanded, 3152).
+-define(wxStyledTextCtrl_ToggleFold, 3153).
+-define(wxStyledTextCtrl_EnsureVisible, 3154).
+-define(wxStyledTextCtrl_SetFoldFlags, 3155).
+-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3156).
+-define(wxStyledTextCtrl_SetTabIndents, 3157).
+-define(wxStyledTextCtrl_GetTabIndents, 3158).
+-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3159).
+-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3160).
+-define(wxStyledTextCtrl_SetMouseDwellTime, 3161).
+-define(wxStyledTextCtrl_GetMouseDwellTime, 3162).
+-define(wxStyledTextCtrl_WordStartPosition, 3163).
+-define(wxStyledTextCtrl_WordEndPosition, 3164).
+-define(wxStyledTextCtrl_SetWrapMode, 3165).
+-define(wxStyledTextCtrl_GetWrapMode, 3166).
+-define(wxStyledTextCtrl_SetWrapVisualFlags, 3167).
+-define(wxStyledTextCtrl_GetWrapVisualFlags, 3168).
+-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3169).
+-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3170).
+-define(wxStyledTextCtrl_SetWrapStartIndent, 3171).
+-define(wxStyledTextCtrl_GetWrapStartIndent, 3172).
+-define(wxStyledTextCtrl_SetLayoutCache, 3173).
+-define(wxStyledTextCtrl_GetLayoutCache, 3174).
+-define(wxStyledTextCtrl_SetScrollWidth, 3175).
+-define(wxStyledTextCtrl_GetScrollWidth, 3176).
+-define(wxStyledTextCtrl_TextWidth, 3177).
+-define(wxStyledTextCtrl_GetEndAtLastLine, 3178).
+-define(wxStyledTextCtrl_TextHeight, 3179).
+-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3180).
+-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3181).
+-define(wxStyledTextCtrl_AppendText, 3182).
+-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3183).
+-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3184).
+-define(wxStyledTextCtrl_TargetFromSelection, 3185).
+-define(wxStyledTextCtrl_LinesJoin, 3186).
+-define(wxStyledTextCtrl_LinesSplit, 3187).
+-define(wxStyledTextCtrl_SetFoldMarginColour, 3188).
+-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3189).
+-define(wxStyledTextCtrl_LineDown, 3190).
+-define(wxStyledTextCtrl_LineDownExtend, 3191).
+-define(wxStyledTextCtrl_LineUp, 3192).
+-define(wxStyledTextCtrl_LineUpExtend, 3193).
+-define(wxStyledTextCtrl_CharLeft, 3194).
+-define(wxStyledTextCtrl_CharLeftExtend, 3195).
+-define(wxStyledTextCtrl_CharRight, 3196).
+-define(wxStyledTextCtrl_CharRightExtend, 3197).
+-define(wxStyledTextCtrl_WordLeft, 3198).
+-define(wxStyledTextCtrl_WordLeftExtend, 3199).
+-define(wxStyledTextCtrl_WordRight, 3200).
+-define(wxStyledTextCtrl_WordRightExtend, 3201).
+-define(wxStyledTextCtrl_Home, 3202).
+-define(wxStyledTextCtrl_HomeExtend, 3203).
+-define(wxStyledTextCtrl_LineEnd, 3204).
+-define(wxStyledTextCtrl_LineEndExtend, 3205).
+-define(wxStyledTextCtrl_DocumentStart, 3206).
+-define(wxStyledTextCtrl_DocumentStartExtend, 3207).
+-define(wxStyledTextCtrl_DocumentEnd, 3208).
+-define(wxStyledTextCtrl_DocumentEndExtend, 3209).
+-define(wxStyledTextCtrl_PageUp, 3210).
+-define(wxStyledTextCtrl_PageUpExtend, 3211).
+-define(wxStyledTextCtrl_PageDown, 3212).
+-define(wxStyledTextCtrl_PageDownExtend, 3213).
+-define(wxStyledTextCtrl_EditToggleOvertype, 3214).
+-define(wxStyledTextCtrl_Cancel, 3215).
+-define(wxStyledTextCtrl_DeleteBack, 3216).
+-define(wxStyledTextCtrl_Tab, 3217).
+-define(wxStyledTextCtrl_BackTab, 3218).
+-define(wxStyledTextCtrl_NewLine, 3219).
+-define(wxStyledTextCtrl_FormFeed, 3220).
+-define(wxStyledTextCtrl_VCHome, 3221).
+-define(wxStyledTextCtrl_VCHomeExtend, 3222).
+-define(wxStyledTextCtrl_ZoomIn, 3223).
+-define(wxStyledTextCtrl_ZoomOut, 3224).
+-define(wxStyledTextCtrl_DelWordLeft, 3225).
+-define(wxStyledTextCtrl_DelWordRight, 3226).
+-define(wxStyledTextCtrl_LineCut, 3227).
+-define(wxStyledTextCtrl_LineDelete, 3228).
+-define(wxStyledTextCtrl_LineTranspose, 3229).
+-define(wxStyledTextCtrl_LineDuplicate, 3230).
+-define(wxStyledTextCtrl_LowerCase, 3231).
+-define(wxStyledTextCtrl_UpperCase, 3232).
+-define(wxStyledTextCtrl_LineScrollDown, 3233).
+-define(wxStyledTextCtrl_LineScrollUp, 3234).
+-define(wxStyledTextCtrl_DeleteBackNotLine, 3235).
+-define(wxStyledTextCtrl_HomeDisplay, 3236).
+-define(wxStyledTextCtrl_HomeDisplayExtend, 3237).
+-define(wxStyledTextCtrl_LineEndDisplay, 3238).
+-define(wxStyledTextCtrl_LineEndDisplayExtend, 3239).
+-define(wxStyledTextCtrl_HomeWrapExtend, 3240).
+-define(wxStyledTextCtrl_LineEndWrap, 3241).
+-define(wxStyledTextCtrl_LineEndWrapExtend, 3242).
+-define(wxStyledTextCtrl_VCHomeWrap, 3243).
+-define(wxStyledTextCtrl_VCHomeWrapExtend, 3244).
+-define(wxStyledTextCtrl_LineCopy, 3245).
+-define(wxStyledTextCtrl_MoveCaretInsideView, 3246).
+-define(wxStyledTextCtrl_LineLength, 3247).
+-define(wxStyledTextCtrl_BraceHighlight, 3248).
+-define(wxStyledTextCtrl_BraceBadLight, 3249).
+-define(wxStyledTextCtrl_BraceMatch, 3250).
+-define(wxStyledTextCtrl_GetViewEOL, 3251).
+-define(wxStyledTextCtrl_SetViewEOL, 3252).
+-define(wxStyledTextCtrl_SetModEventMask, 3253).
+-define(wxStyledTextCtrl_GetEdgeColumn, 3254).
+-define(wxStyledTextCtrl_SetEdgeColumn, 3255).
+-define(wxStyledTextCtrl_SetEdgeMode, 3256).
+-define(wxStyledTextCtrl_GetEdgeMode, 3257).
+-define(wxStyledTextCtrl_GetEdgeColour, 3258).
+-define(wxStyledTextCtrl_SetEdgeColour, 3259).
+-define(wxStyledTextCtrl_SearchAnchor, 3260).
+-define(wxStyledTextCtrl_SearchNext, 3261).
+-define(wxStyledTextCtrl_SearchPrev, 3262).
+-define(wxStyledTextCtrl_LinesOnScreen, 3263).
+-define(wxStyledTextCtrl_UsePopUp, 3264).
+-define(wxStyledTextCtrl_SelectionIsRectangle, 3265).
+-define(wxStyledTextCtrl_SetZoom, 3266).
+-define(wxStyledTextCtrl_GetZoom, 3267).
+-define(wxStyledTextCtrl_GetModEventMask, 3268).
+-define(wxStyledTextCtrl_SetSTCFocus, 3269).
+-define(wxStyledTextCtrl_GetSTCFocus, 3270).
+-define(wxStyledTextCtrl_SetStatus, 3271).
+-define(wxStyledTextCtrl_GetStatus, 3272).
+-define(wxStyledTextCtrl_SetMouseDownCaptures, 3273).
+-define(wxStyledTextCtrl_GetMouseDownCaptures, 3274).
+-define(wxStyledTextCtrl_SetSTCCursor, 3275).
+-define(wxStyledTextCtrl_GetSTCCursor, 3276).
+-define(wxStyledTextCtrl_SetControlCharSymbol, 3277).
+-define(wxStyledTextCtrl_GetControlCharSymbol, 3278).
+-define(wxStyledTextCtrl_WordPartLeft, 3279).
+-define(wxStyledTextCtrl_WordPartLeftExtend, 3280).
+-define(wxStyledTextCtrl_WordPartRight, 3281).
+-define(wxStyledTextCtrl_WordPartRightExtend, 3282).
+-define(wxStyledTextCtrl_SetVisiblePolicy, 3283).
+-define(wxStyledTextCtrl_DelLineLeft, 3284).
+-define(wxStyledTextCtrl_DelLineRight, 3285).
+-define(wxStyledTextCtrl_GetXOffset, 3286).
+-define(wxStyledTextCtrl_ChooseCaretX, 3287).
+-define(wxStyledTextCtrl_SetXCaretPolicy, 3288).
+-define(wxStyledTextCtrl_SetYCaretPolicy, 3289).
+-define(wxStyledTextCtrl_GetPrintWrapMode, 3290).
+-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3291).
+-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3292).
+-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3293).
+-define(wxStyledTextCtrl_SetHotspotSingleLine, 3294).
+-define(wxStyledTextCtrl_ParaDownExtend, 3295).
+-define(wxStyledTextCtrl_ParaUp, 3296).
+-define(wxStyledTextCtrl_ParaUpExtend, 3297).
+-define(wxStyledTextCtrl_PositionBefore, 3298).
+-define(wxStyledTextCtrl_PositionAfter, 3299).
+-define(wxStyledTextCtrl_CopyRange, 3300).
+-define(wxStyledTextCtrl_CopyText, 3301).
+-define(wxStyledTextCtrl_SetSelectionMode, 3302).
+-define(wxStyledTextCtrl_GetSelectionMode, 3303).
+-define(wxStyledTextCtrl_LineDownRectExtend, 3304).
+-define(wxStyledTextCtrl_LineUpRectExtend, 3305).
+-define(wxStyledTextCtrl_CharLeftRectExtend, 3306).
+-define(wxStyledTextCtrl_CharRightRectExtend, 3307).
+-define(wxStyledTextCtrl_HomeRectExtend, 3308).
+-define(wxStyledTextCtrl_VCHomeRectExtend, 3309).
+-define(wxStyledTextCtrl_LineEndRectExtend, 3310).
+-define(wxStyledTextCtrl_PageUpRectExtend, 3311).
+-define(wxStyledTextCtrl_PageDownRectExtend, 3312).
+-define(wxStyledTextCtrl_StutteredPageUp, 3313).
+-define(wxStyledTextCtrl_StutteredPageUpExtend, 3314).
+-define(wxStyledTextCtrl_StutteredPageDown, 3315).
+-define(wxStyledTextCtrl_StutteredPageDownExtend, 3316).
+-define(wxStyledTextCtrl_WordLeftEnd, 3317).
+-define(wxStyledTextCtrl_WordLeftEndExtend, 3318).
+-define(wxStyledTextCtrl_WordRightEnd, 3319).
+-define(wxStyledTextCtrl_WordRightEndExtend, 3320).
+-define(wxStyledTextCtrl_SetWhitespaceChars, 3321).
+-define(wxStyledTextCtrl_SetCharsDefault, 3322).
+-define(wxStyledTextCtrl_AutoCompGetCurrent, 3323).
+-define(wxStyledTextCtrl_Allocate, 3324).
+-define(wxStyledTextCtrl_FindColumn, 3325).
+-define(wxStyledTextCtrl_GetCaretSticky, 3326).
+-define(wxStyledTextCtrl_SetCaretSticky, 3327).
+-define(wxStyledTextCtrl_ToggleCaretSticky, 3328).
+-define(wxStyledTextCtrl_SetPasteConvertEndings, 3329).
+-define(wxStyledTextCtrl_GetPasteConvertEndings, 3330).
+-define(wxStyledTextCtrl_SelectionDuplicate, 3331).
+-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3332).
+-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3333).
+-define(wxStyledTextCtrl_StartRecord, 3334).
+-define(wxStyledTextCtrl_StopRecord, 3335).
+-define(wxStyledTextCtrl_SetLexer, 3336).
+-define(wxStyledTextCtrl_GetLexer, 3337).
+-define(wxStyledTextCtrl_Colourise, 3338).
+-define(wxStyledTextCtrl_SetProperty, 3339).
+-define(wxStyledTextCtrl_SetKeyWords, 3340).
+-define(wxStyledTextCtrl_SetLexerLanguage, 3341).
+-define(wxStyledTextCtrl_GetProperty, 3342).
+-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3343).
+-define(wxStyledTextCtrl_GetCurrentLine, 3344).
+-define(wxStyledTextCtrl_StyleSetSpec, 3345).
+-define(wxStyledTextCtrl_StyleSetFont, 3346).
+-define(wxStyledTextCtrl_StyleSetFontAttr, 3347).
+-define(wxStyledTextCtrl_StyleSetCharacterSet, 3348).
+-define(wxStyledTextCtrl_StyleSetFontEncoding, 3349).
+-define(wxStyledTextCtrl_CmdKeyExecute, 3350).
+-define(wxStyledTextCtrl_SetMargins, 3351).
+-define(wxStyledTextCtrl_GetSelection, 3352).
+-define(wxStyledTextCtrl_PointFromPosition, 3353).
+-define(wxStyledTextCtrl_ScrollToLine, 3354).
+-define(wxStyledTextCtrl_ScrollToColumn, 3355).
+-define(wxStyledTextCtrl_SetVScrollBar, 3356).
+-define(wxStyledTextCtrl_SetHScrollBar, 3357).
+-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3358).
+-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3359).
+-define(wxStyledTextCtrl_SaveFile, 3360).
+-define(wxStyledTextCtrl_LoadFile, 3361).
+-define(wxStyledTextCtrl_DoDragOver, 3362).
+-define(wxStyledTextCtrl_DoDropText, 3363).
+-define(wxStyledTextCtrl_GetUseAntiAliasing, 3364).
+-define(wxStyledTextCtrl_AddTextRaw, 3365).
+-define(wxStyledTextCtrl_InsertTextRaw, 3366).
+-define(wxStyledTextCtrl_GetCurLineRaw, 3367).
+-define(wxStyledTextCtrl_GetLineRaw, 3368).
+-define(wxStyledTextCtrl_GetSelectedTextRaw, 3369).
+-define(wxStyledTextCtrl_GetTextRangeRaw, 3370).
+-define(wxStyledTextCtrl_SetTextRaw, 3371).
+-define(wxStyledTextCtrl_GetTextRaw, 3372).
+-define(wxStyledTextCtrl_AppendTextRaw, 3373).
+-define(wxArtProvider_GetBitmap, 3374).
+-define(wxArtProvider_GetIcon, 3375).
+-define(wxTreeEvent_GetKeyCode, 3376).
+-define(wxTreeEvent_GetItem, 3377).
+-define(wxTreeEvent_GetKeyEvent, 3378).
+-define(wxTreeEvent_GetLabel, 3379).
+-define(wxTreeEvent_GetOldItem, 3380).
+-define(wxTreeEvent_GetPoint, 3381).
+-define(wxTreeEvent_IsEditCancelled, 3382).
+-define(wxTreeEvent_SetToolTip, 3383).
+-define(wxBookCtrlEvent_GetOldSelection, 3384).
+-define(wxBookCtrlEvent_GetSelection, 3385).
+-define(wxBookCtrlEvent_SetOldSelection, 3386).
+-define(wxBookCtrlEvent_SetSelection, 3387).
+-define(wxFileDataObject_new, 3388).
+-define(wxFileDataObject_AddFile, 3389).
+-define(wxFileDataObject_GetFilenames, 3390).
+-define(wxFileDataObject_destroy, 3391).
+-define(wxTextDataObject_new, 3392).
+-define(wxTextDataObject_GetTextLength, 3393).
+-define(wxTextDataObject_GetText, 3394).
+-define(wxTextDataObject_SetText, 3395).
+-define(wxTextDataObject_destroy, 3396).
+-define(wxBitmapDataObject_new_1_1, 3397).
+-define(wxBitmapDataObject_new_1_0, 3398).
+-define(wxBitmapDataObject_GetBitmap, 3399).
+-define(wxBitmapDataObject_SetBitmap, 3400).
+-define(wxBitmapDataObject_destroy, 3401).
+-define(wxClipboard_new, 3402).
+-define(wxClipboard_destruct, 3403).
+-define(wxClipboard_AddData, 3404).
+-define(wxClipboard_Clear, 3405).
+-define(wxClipboard_Close, 3406).
+-define(wxClipboard_Flush, 3407).
+-define(wxClipboard_GetData, 3408).
+-define(wxClipboard_IsOpened, 3409).
+-define(wxClipboard_Open, 3410).
+-define(wxClipboard_SetData, 3411).
+-define(wxClipboard_UsePrimarySelection, 3412).
+-define(wxClipboard_IsSupported, 3413).
+-define(wxClipboard_Get, 3414).
+-define(wxSpinEvent_GetPosition, 3415).
+-define(wxSpinEvent_SetPosition, 3416).
+-define(wxSplitterWindow_new_0, 3417).
+-define(wxSplitterWindow_new_2, 3418).
+-define(wxSplitterWindow_destruct, 3419).
+-define(wxSplitterWindow_Create, 3420).
+-define(wxSplitterWindow_GetMinimumPaneSize, 3421).
+-define(wxSplitterWindow_GetSashGravity, 3422).
+-define(wxSplitterWindow_GetSashPosition, 3423).
+-define(wxSplitterWindow_GetSplitMode, 3424).
+-define(wxSplitterWindow_GetWindow1, 3425).
+-define(wxSplitterWindow_GetWindow2, 3426).
+-define(wxSplitterWindow_Initialize, 3427).
+-define(wxSplitterWindow_IsSplit, 3428).
+-define(wxSplitterWindow_ReplaceWindow, 3429).
+-define(wxSplitterWindow_SetSashGravity, 3430).
+-define(wxSplitterWindow_SetSashPosition, 3431).
+-define(wxSplitterWindow_SetMinimumPaneSize, 3432).
+-define(wxSplitterWindow_SetSplitMode, 3433).
+-define(wxSplitterWindow_SplitHorizontally, 3434).
+-define(wxSplitterWindow_SplitVertically, 3435).
+-define(wxSplitterWindow_Unsplit, 3436).
+-define(wxSplitterWindow_UpdateSize, 3437).
+-define(wxSplitterEvent_GetSashPosition, 3438).
+-define(wxSplitterEvent_GetX, 3439).
+-define(wxSplitterEvent_GetY, 3440).
+-define(wxSplitterEvent_GetWindowBeingRemoved, 3441).
+-define(wxSplitterEvent_SetSashPosition, 3442).
+-define(wxHtmlWindow_new_0, 3443).
+-define(wxHtmlWindow_new_2, 3444).
+-define(wxHtmlWindow_AppendToPage, 3445).
+-define(wxHtmlWindow_GetOpenedAnchor, 3446).
+-define(wxHtmlWindow_GetOpenedPage, 3447).
+-define(wxHtmlWindow_GetOpenedPageTitle, 3448).
+-define(wxHtmlWindow_GetRelatedFrame, 3449).
+-define(wxHtmlWindow_HistoryBack, 3450).
+-define(wxHtmlWindow_HistoryCanBack, 3451).
+-define(wxHtmlWindow_HistoryCanForward, 3452).
+-define(wxHtmlWindow_HistoryClear, 3453).
+-define(wxHtmlWindow_HistoryForward, 3454).
+-define(wxHtmlWindow_LoadFile, 3455).
+-define(wxHtmlWindow_LoadPage, 3456).
+-define(wxHtmlWindow_SelectAll, 3457).
+-define(wxHtmlWindow_SelectionToText, 3458).
+-define(wxHtmlWindow_SelectLine, 3459).
+-define(wxHtmlWindow_SelectWord, 3460).
+-define(wxHtmlWindow_SetBorders, 3461).
+-define(wxHtmlWindow_SetFonts, 3462).
+-define(wxHtmlWindow_SetPage, 3463).
+-define(wxHtmlWindow_SetRelatedFrame, 3464).
+-define(wxHtmlWindow_SetRelatedStatusBar_1, 3465).
+-define(wxHtmlWindow_SetRelatedStatusBar_2, 3466).
+-define(wxHtmlWindow_ToText, 3467).
+-define(wxHtmlWindow_destroy, 3468).
+-define(wxHtmlLinkEvent_GetLinkInfo, 3469).
+-define(wxSystemSettings_GetColour, 3470).
+-define(wxSystemSettings_GetFont, 3471).
+-define(wxSystemSettings_GetMetric, 3472).
+-define(wxSystemSettings_GetScreenType, 3473).
+-define(wxSystemOptions_GetOption, 3474).
+-define(wxSystemOptions_GetOptionInt, 3475).
+-define(wxSystemOptions_HasOption, 3476).
+-define(wxSystemOptions_IsFalse, 3477).
+-define(wxSystemOptions_SetOption_2_1, 3478).
+-define(wxSystemOptions_SetOption_2_0, 3479).
+-define(wxAuiNotebookEvent_SetSelection, 3480).
+-define(wxAuiNotebookEvent_GetSelection, 3481).
+-define(wxAuiNotebookEvent_SetOldSelection, 3482).
+-define(wxAuiNotebookEvent_GetOldSelection, 3483).
+-define(wxAuiNotebookEvent_SetDragSource, 3484).
+-define(wxAuiNotebookEvent_GetDragSource, 3485).
+-define(wxAuiManagerEvent_SetManager, 3486).
+-define(wxAuiManagerEvent_GetManager, 3487).
+-define(wxAuiManagerEvent_SetPane, 3488).
+-define(wxAuiManagerEvent_GetPane, 3489).
+-define(wxAuiManagerEvent_SetButton, 3490).
+-define(wxAuiManagerEvent_GetButton, 3491).
+-define(wxAuiManagerEvent_SetDC, 3492).
+-define(wxAuiManagerEvent_GetDC, 3493).
+-define(wxAuiManagerEvent_Veto, 3494).
+-define(wxAuiManagerEvent_GetVeto, 3495).
+-define(wxAuiManagerEvent_SetCanVeto, 3496).
+-define(wxAuiManagerEvent_CanVeto, 3497).
+-define(wxLogNull_new, 3498).
+-define(wxLogNull_destruct, 3499).
+-define(wxTaskBarIcon_new, 3500).
+-define(wxTaskBarIcon_destruct, 3501).
+-define(wxTaskBarIcon_PopupMenu, 3502).
+-define(wxTaskBarIcon_RemoveIcon, 3503).
+-define(wxTaskBarIcon_SetIcon, 3504).
+-define(wxLocale_new_0, 3505).
+-define(wxLocale_new_2_0, 3506).
+-define(wxLocale_new_2_1, 3507).
+-define(wxLocale_destruct, 3508).
+-define(wxLocale_Init_1, 3509).
+-define(wxLocale_Init_2, 3510).
+-define(wxLocale_AddCatalog_1, 3511).
+-define(wxLocale_AddCatalog_2, 3512).
+-define(wxLocale_AddCatalog_3, 3513).
+-define(wxLocale_AddCatalogLookupPathPrefix, 3514).
+-define(wxLocale_GetCanonicalName, 3515).
+-define(wxLocale_GetLanguage, 3516).
+-define(wxLocale_GetLanguageName, 3517).
+-define(wxLocale_GetLocale, 3518).
+-define(wxLocale_GetName, 3519).
+-define(wxLocale_GetString_2, 3520).
+-define(wxLocale_GetString_4, 3521).
+-define(wxLocale_GetHeaderValue, 3522).
+-define(wxLocale_GetSysName, 3523).
+-define(wxLocale_GetSystemEncoding, 3524).
+-define(wxLocale_GetSystemEncodingName, 3525).
+-define(wxLocale_GetSystemLanguage, 3526).
+-define(wxLocale_IsLoaded, 3527).
+-define(wxLocale_IsOk, 3528).
+-define(wxActivateEvent_GetActive, 3529).
+-define(wxPopupWindow_new_0, 3530).
+-define(wxPopupWindow_new_2, 3531).
+-define(wxPopupWindow_Create, 3532).
+-define(wxPopupWindow_Position, 3533).
+-define(wxPopupWindow_destroy, 3534).
+-define(wxPopupTransientWindow_new_0, 3535).
+-define(wxPopupTransientWindow_new_2, 3536).
+-define(wxPopupTransientWindow_Popup, 3537).
+-define(wxPopupTransientWindow_Dismiss, 3538).
+-define(wxPopupTransientWindow_destroy, 3539).
+-define(wxOverlay_new, 3540).
+-define(wxOverlay_destruct, 3541).
+-define(wxOverlay_Reset, 3542).
+-define(wxDCOverlay_new_6, 3543).
+-define(wxDCOverlay_new_2, 3544).
+-define(wxDCOverlay_destruct, 3545).
+-define(wxDCOverlay_Clear, 3546).
+-define(wxDropFilesEvent_GetPosition, 3547).
+-define(wxDropFilesEvent_GetNumberOfFiles, 3548).
+-define(wxDropFilesEvent_GetFiles, 3549).
+-define(wxDisplay_new_0, 3550).
+-define(wxDisplay_new_1_0, 3551).
+-define(wxDisplay_new_1_1, 3552).
+-define(wxDisplay_destruct, 3553).
+-define(wxDisplay_IsOk, 3554).
+-define(wxDisplay_GetClientArea, 3555).
+-define(wxDisplay_GetGeometry, 3556).
+-define(wxDisplay_GetName, 3557).
+-define(wxDisplay_IsPrimary, 3558).
+-define(wxDisplay_GetCount, 3559).
+-define(wxDisplay_GetFromPoint, 3560).
+-define(wxDisplay_GetFromWindow, 3561).
+-define(wxDisplay_GetPPI, 3562).
+-define(wxGCDC_new_1, 3563).
+-define(wxGCDC_new_0, 3566).
+-define(wxGCDC_destruct, 3567).
+-define(wxGCDC_GetGraphicsContext, 3568).
+-define(wxGCDC_SetGraphicsContext, 3569).
+-define(wxNotificationMessage_new_0, 3570).
+-define(wxNotificationMessage_new_2, 3571).
+-define(wxNotificationMessage_destruct, 3572).
+-define(wxNotificationMessage_AddAction, 3573).
+-define(wxNotificationMessage_Close, 3574).
+-define(wxNotificationMessage_SetFlags, 3575).
+-define(wxNotificationMessage_SetIcon, 3576).
+-define(wxNotificationMessage_SetMessage, 3577).
+-define(wxNotificationMessage_SetParent, 3578).
+-define(wxNotificationMessage_SetTitle, 3579).
+-define(wxNotificationMessage_Show, 3580).
+-define(wxNotificationMessage_UseTaskBarIcon, 3581).
+-define(wxNotificationMessage_MSWUseToasts, 3582).
+-define(wxWebView_New, 3584).
+-define(wxWebView_GetCurrentTitle, 3585).
+-define(wxWebView_GetCurrentURL, 3586).
+-define(wxWebView_GetPageSource, 3587).
+-define(wxWebView_GetPageText, 3588).
+-define(wxWebView_IsBusy, 3589).
+-define(wxWebView_IsEditable, 3590).
+-define(wxWebView_LoadURL, 3591).
+-define(wxWebView_Print, 3592).
+-define(wxWebView_Reload, 3593).
+-define(wxWebView_RunScript, 3594).
+-define(wxWebView_SetEditable, 3595).
+-define(wxWebView_SetPage, 3596).
+-define(wxWebView_Stop, 3597).
+-define(wxWebView_CanCopy, 3598).
+-define(wxWebView_CanCut, 3599).
+-define(wxWebView_CanPaste, 3600).
+-define(wxWebView_Copy, 3601).
+-define(wxWebView_Cut, 3602).
+-define(wxWebView_Paste, 3603).
+-define(wxWebView_EnableContextMenu, 3604).
+-define(wxWebView_IsContextMenuEnabled, 3605).
+-define(wxWebView_CanGoBack, 3606).
+-define(wxWebView_CanGoForward, 3607).
+-define(wxWebView_ClearHistory, 3608).
+-define(wxWebView_EnableHistory, 3609).
+-define(wxWebView_GoBack, 3610).
+-define(wxWebView_GoForward, 3611).
+-define(wxWebView_ClearSelection, 3612).
+-define(wxWebView_DeleteSelection, 3613).
+-define(wxWebView_GetSelectedSource, 3614).
+-define(wxWebView_GetSelectedText, 3615).
+-define(wxWebView_HasSelection, 3616).
+-define(wxWebView_SelectAll, 3617).
+-define(wxWebView_CanRedo, 3618).
+-define(wxWebView_CanUndo, 3619).
+-define(wxWebView_Redo, 3620).
+-define(wxWebView_Undo, 3621).
+-define(wxWebView_Find, 3622).
+-define(wxWebView_CanSetZoomType, 3623).
+-define(wxWebView_GetZoom, 3624).
+-define(wxWebView_GetZoomType, 3625).
+-define(wxWebView_SetZoom, 3626).
+-define(wxWebView_SetZoomType, 3627).
+-define(wxWebView_GetZoomFactor, 3628).
+-define(wxWebView_SetZoomFactor, 3629).
+-define(wxWebView_IsBackendAvailable, 3630).
+-define(wxWebViewEvent_GetString, 3631).
+-define(wxWebViewEvent_GetInt, 3632).
+-define(wxWebViewEvent_GetTarget, 3633).
+-define(wxWebViewEvent_GetURL, 3634).
diff --git a/lib/wx/src/wxe_master.erl b/lib/wx/src/wxe_master.erl
index 5724457ae7..f0bb1e64e7 100644
--- a/lib/wx/src/wxe_master.erl
+++ b/lib/wx/src/wxe_master.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -80,8 +80,9 @@ init_opengl() ->
case get(wx_init_opengl) of
true -> {ok, "already initialized"};
_ ->
- Opaque = gl:lookup_func(),
- {ok, wxe_util:init_opengl(Opaque)}
+ Opaque = gl:lookup_func(functions),
+ Debug = gl:lookup_func(function_names),
+ {ok, wxe_util:init_opengl(Opaque, Debug)}
end.
%%--------------------------------------------------------------------
diff --git a/lib/wx/src/wxe_util.erl b/lib/wx/src/wxe_util.erl
index 1d5f15f131..217e7118ff 100644
--- a/lib/wx/src/wxe_util.erl
+++ b/lib/wx/src/wxe_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,14 +37,14 @@
queue_cmd/11,queue_cmd/12,queue_cmd/13,queue_cmd/14,queue_cmd/15,
make_env/0, delete_env/1, get_consts/0,
debug_ping/0, debug_driver/1,
- init_opengl/1
+ init_opengl/2
]).
-nifs([queue_cmd/1,queue_cmd/2,queue_cmd/3,queue_cmd/4,queue_cmd/5,
queue_cmd/6,queue_cmd/7,queue_cmd/8,queue_cmd/9,queue_cmd/10,
queue_cmd/11,queue_cmd/12,queue_cmd/13,queue_cmd/14,queue_cmd/15,
make_env/0, delete_env/1, debug_driver/1, get_consts_impl/0,
- init_opengl/1
+ init_opengl/2
]).
-export([priv_dir/2, opt_error_log/3, init_nif/1]).
@@ -85,7 +85,7 @@ get_consts() ->
get_consts_impl(),
rec(?WXE_GET_CONSTS).
-init_opengl(_) -> ?NIF_ERROR.
+init_opengl(_,_) -> ?NIF_ERROR.
get_consts_impl() -> ?NIF_ERROR.
debug_ping() -> queue_cmd(?WXE_DEBUG_PING).
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index 7cab2d85fa..5275defce6 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -244,6 +244,8 @@ clipboard(Config) ->
wxTextCtrl:connect(Ctrl, command_text_paste, [{skip, true}]),
wxWindow:show(Frame),
+ BlockWxDialogs = wxLogNull:new(),
+
CB = ?mt(wxClipboard, wxClipboard:get()),
wxClipboard:usePrimarySelection(CB),
?m(false, wx:is_null(CB)),
@@ -271,7 +273,10 @@ clipboard(Config) ->
Paste = ?mt(wxTextDataObject, wxTextDataObject:new([{text,"From Erlang"}])),
case wxClipboard:addData(CB,Paste) of
true ->
- ?log("Put text on clipboard~n", []);
+ ?log("Put text on clipboard~n", []),
+ ?log("Flushing ~n",[]),
+ wxClipboard:flush(CB),
+ ?log("Stopping ~n",[]);
false ->
?log("Couldn't copy data to clipboard~n",[])
end,
@@ -279,9 +284,7 @@ clipboard(Config) ->
false ->
?log("Clipboard open failed~n",[])
end,
- ?log("Flushing ~n",[]),
- wxClipboard:flush(CB),
- ?log("Stopping ~n",[]),
+ wxLogNull:destroy(BlockWxDialogs),
wx_test_lib:wx_destroy(Frame,Config).
diff --git a/lib/wx/test/wx_opengl_SUITE.erl b/lib/wx/test/wx_opengl_SUITE.erl
index 3ec75c662a..fb3e5ba598 100644
--- a/lib/wx/test/wx_opengl_SUITE.erl
+++ b/lib/wx/test/wx_opengl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--export([canvas/1, glu_tesselation/1]).
+-export([canvas/1, glu_tesselation/1, debugMessage/1]).
-include("wx_test_lib.hrl").
-include_lib("wx/include/gl.hrl").
@@ -55,7 +55,7 @@ end_per_testcase(Func,Config) ->
suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap,{minutes,2}}].
all() ->
- [canvas, glu_tesselation].
+ [canvas, glu_tesselation, debugMessage].
groups() ->
[].
@@ -101,15 +101,8 @@ canvas(Config) ->
%% ?WX_GL_CORE_PROFILE,
?WX_GL_DEPTH_SIZE,24,0]}],
Canvas = ?mt(wxGLCanvas, wxGLCanvas:new(Frame, [{style,?wxFULL_REPAINT_ON_RESIZE}|Attrs])),
- SetContext =
- try %% 3.0 API
- Context = wxGLContext:new(Canvas),
- fun() -> ?m(true, wxGLCanvas:setCurrent(Canvas, Context)) end
- catch _:Reason:ST -> %% 2.8 API
- io:format("Using old api: ~p~n ~p~n",[Reason, ST]),
- ?m(false, wx:is_null(wxGLCanvas:getContext(Canvas))),
- fun() -> ?m(ok, wxGLCanvas:setCurrent(Canvas)) end
- end,
+ Context = wxGLContext:new(Canvas),
+ SetContext = fun() -> ?m(true, wxGLCanvas:setCurrent(Canvas, Context)) end,
wxFrame:connect(Frame, show),
?m(true, wxWindow:show(Frame)),
@@ -241,14 +234,8 @@ glu_tesselation(Config) ->
after 1000 -> exit(show_timeout)
end,
- try %% 3.0 API
- Context = wxGLContext:new(Canvas),
- wxGLCanvas:setCurrent(Canvas, Context)
- catch _:Reason:ST -> %% 2.8 API
- io:format("Using old api: ~p~n ~p~n",[Reason, ST]),
- ?m(false, wx:is_null(wxGLCanvas:getContext(Canvas))),
- ?m(ok, wxGLCanvas:setCurrent(Canvas))
- end,
+ Context = wxGLContext:new(Canvas),
+ wxGLCanvas:setCurrent(Canvas, Context),
Simple = ?m({_,_}, glu:tesselate({0.0,0.0,1.0}, [{-1.0,0.0,0.0},{1.0,0.0,0.0},{0.0,1.0,0.0}])),
io:format("Simple ~p~n",[Simple]),
@@ -268,4 +255,50 @@ glu_tesselation(Config) ->
wx_test_lib:wx_destroy(Frame, Config).
-
+debugMessage(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
+debugMessage(Config) ->
+ WX = ?mr(wx_ref, wx:new()),
+ Frame = wxFrame:new(WX,1,"Hello 3D-World",[]),
+ case {?wxMAJOR_VERSION, ?wxMINOR_VERSION} of
+ {WxMajor,WxMinor} when WxMajor >= 3, WxMinor >= 2 ->
+ Attrs = [{attribList, [?WX_GL_RGBA,?WX_GL_DOUBLEBUFFER,?WX_GL_DEBUG,0]}],
+ Canvas = ?mt(wxGLCanvas, wxGLCanvas:new(Frame, Attrs)),
+ wxFrame:connect(Frame, show),
+ ?m(true, wxWindow:show(Frame)),
+
+ receive #wx{event=#wxShow{}} -> ok
+ after 1000 -> exit(show_timeout)
+ end,
+
+ Context = wxGLContext:new(Canvas),
+ wxGLCanvas:setCurrent(Canvas, Context),
+
+ case {gl:getIntegerv(?GL_MAJOR_VERSION),gl:getIntegerv(?GL_MINOR_VERSION)} of
+ {[Major|_], [Minor|_]} when Major >= 4, Minor >= 3 ->
+ io:format("~nVersion: ~p~n", [{Major,Minor}]),
+ ByteCount = 5000,
+ Count = 10,
+ %% Before any log insertion:
+ A = gl:getDebugMessageLog(Count, ByteCount),
+ io:format( "A = ~p~n", [ A ] ),
+
+ Msg1 = "Hello!",
+ gl:debugMessageInsert(?GL_DEBUG_SOURCE_APPLICATION, ?GL_DEBUG_TYPE_ERROR,
+ 10, ?GL_DEBUG_SEVERITY_HIGH, Msg1),
+ Msg2 = "Goodbye...",
+ gl:debugMessageInsert(?GL_DEBUG_SOURCE_APPLICATION, ?GL_DEBUG_TYPE_ERROR,
+ 11, ?GL_DEBUG_SEVERITY_HIGH, Msg2),
+
+ B = gl:getDebugMessageLog(Count, ByteCount),
+ io:format("B = ~p~n", [B]),
+
+ C = gl:getDebugMessageLog(Count, ByteCount),
+ io:format("C = ~p~n", [C]);
+ Versions ->
+ io:format("Not supported version: ~p~n", [Versions])
+ end;
+ _ -> ok
+ end,
+ wx_test_lib:wx_destroy(Frame, Config).
+
+
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index e7144bd6a2..78f0fd3395 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 2.2.1
+WX_VSN = 2.2.2
diff --git a/make/app_targets.mk b/make/app_targets.mk
index 2bf1421f80..64a5c47dfa 100644
--- a/make/app_targets.mk
+++ b/make/app_targets.mk
@@ -22,9 +22,11 @@ APPLICATION ?= $(basename $(notdir $(PWD)))
.PHONY: test info gclean dialyzer dialyzer_plt dclean
+ifndef NO_TEST_TARGET
test:
TEST_NEEDS_RELEASE=$(TEST_NEEDS_RELEASE) TYPE=$(TYPE) \
$(ERL_TOP)/make/test_target_script.sh $(ERL_TOP)
+endif
info:
@echo "$(APPLICATION)_VSN: $(VSN)"
diff --git a/make/autoconf/otp.m4 b/make/autoconf/otp.m4
index 6d9d39a016..f543101599 100644
--- a/make/autoconf/otp.m4
+++ b/make/autoconf/otp.m4
@@ -1458,7 +1458,7 @@ AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
[
ethr_cv_arm_isb_sy_instr=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
- __asm__ __volatile__("isb sy" : : : "memory");
+ __asm__ __volatile__("isb sy\n" : : : "memory");
]])],[ethr_cv_arm_isb_sy_instr=yes],[])
])
if test $ethr_cv_arm_isb_sy_instr = yes; then
@@ -1468,7 +1468,7 @@ AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
[
ethr_cv_arm_dc_cvau_instr=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
- char data[512]; __asm__ __volatile__("dc cvau, %0" : "r" (data) : : "memory");
+ char data[512]; __asm__ __volatile__("dc cvau, %0\n" :: "r" (data) : "memory");
]])],[ethr_cv_arm_dc_cvau_instr=yes],[])
])
if test $ethr_cv_arm_dc_cvau_instr = yes; then
@@ -1478,7 +1478,7 @@ AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
[
ethr_cv_arm_ic_ivau_instr=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
- char data[512]; __asm__ __volatile__("ic ivau, %0" : "r" (data) : : "memory");
+ char data[512]; __asm__ __volatile__("ic ivau, %0\n" :: "r" (data) : "memory");
]])],[ethr_cv_arm_ic_ivau_instr=yes],[])
])
if test $ethr_cv_arm_ic_ivau_instr = yes; then
diff --git a/otp_versions.table b/otp_versions.table
index 33572d8f01..9da37263b9 100644
--- a/otp_versions.table
+++ b/otp_versions.table
@@ -1,3 +1,5 @@
+OTP-25.3.2 : compiler-8.2.6 erts-13.2.2 os_mon-2.8.2 # asn1-5.0.21 common_test-1.24 crypto-5.1.4 debugger-5.3.1 dialyzer-5.0.5 diameter-2.2.7 edoc-1.2 eldap-1.2.11 erl_docgen-1.4 erl_interface-5.3.2 et-1.6.5 eunit-2.8.2 ftp-1.1.4 inets-8.3.1 jinterface-1.13.2 kernel-8.5.4 megaco-4.4.3 mnesia-4.21.4 observer-2.14 odbc-2.14 parsetools-2.4.1 public_key-1.13.3 reltool-0.9.1 runtime_tools-1.19 sasl-4.2 snmp-5.13.5 ssh-4.15.3 ssl-10.9.1 stdlib-4.3.1 syntax_tools-3.0.1 tftp-1.0.4 tools-3.5.3 wx-2.2.2 xmerl-1.3.31 :
+OTP-25.3.1 : compiler-8.2.5 crypto-5.1.4 eldap-1.2.11 erl_interface-5.3.2 erts-13.2.1 inets-8.3.1 snmp-5.13.5 ssl-10.9.1 stdlib-4.3.1 wx-2.2.2 # asn1-5.0.21 common_test-1.24 debugger-5.3.1 dialyzer-5.0.5 diameter-2.2.7 edoc-1.2 erl_docgen-1.4 et-1.6.5 eunit-2.8.2 ftp-1.1.4 jinterface-1.13.2 kernel-8.5.4 megaco-4.4.3 mnesia-4.21.4 observer-2.14 odbc-2.14 os_mon-2.8.1 parsetools-2.4.1 public_key-1.13.3 reltool-0.9.1 runtime_tools-1.19 sasl-4.2 ssh-4.15.3 syntax_tools-3.0.1 tftp-1.0.4 tools-3.5.3 xmerl-1.3.31 :
OTP-25.3 : common_test-1.24 compiler-8.2.4 crypto-5.1.3 debugger-5.3.1 dialyzer-5.0.5 erl_interface-5.3.1 erts-13.2 eunit-2.8.2 ftp-1.1.4 inets-8.3 jinterface-1.13.2 kernel-8.5.4 megaco-4.4.3 mnesia-4.21.4 os_mon-2.8.1 public_key-1.13.3 reltool-0.9.1 snmp-5.13.4 ssh-4.15.3 ssl-10.9 stdlib-4.3 syntax_tools-3.0.1 tftp-1.0.4 xmerl-1.3.31 # asn1-5.0.21 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 et-1.6.5 observer-2.14 odbc-2.14 parsetools-2.4.1 runtime_tools-1.19 sasl-4.2 tools-3.5.3 wx-2.2.1 :
OTP-25.2.3 : erts-13.1.5 inets-8.2.2 ssh-4.15.2 ssl-10.8.7 # asn1-5.0.21 common_test-1.23.3 compiler-8.2.3 crypto-5.1.2 debugger-5.3 dialyzer-5.0.4 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 et-1.6.5 eunit-2.8.1 ftp-1.1.3 jinterface-1.13.1 kernel-8.5.3 megaco-4.4.2 mnesia-4.21.3 observer-2.14 odbc-2.14 os_mon-2.8 parsetools-2.4.1 public_key-1.13.2 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13.3 stdlib-4.2 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2.1 xmerl-1.3.30 :
OTP-25.2.2 : ftp-1.1.3 # asn1-5.0.21 common_test-1.23.3 compiler-8.2.3 crypto-5.1.2 debugger-5.3 dialyzer-5.0.4 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 erts-13.1.4 et-1.6.5 eunit-2.8.1 inets-8.2.1 jinterface-1.13.1 kernel-8.5.3 megaco-4.4.2 mnesia-4.21.3 observer-2.14 odbc-2.14 os_mon-2.8 parsetools-2.4.1 public_key-1.13.2 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13.3 ssh-4.15.1 ssl-10.8.6 stdlib-4.2 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2.1 xmerl-1.3.30 :
@@ -12,6 +14,7 @@ OTP-25.0.3 : erts-13.0.3 ssl-10.8.3 # asn1-5.0.19 common_test-1.23 compiler-8.2
OTP-25.0.2 : erts-13.0.2 ssl-10.8.2 # asn1-5.0.19 common_test-1.23 compiler-8.2 crypto-5.1.1 debugger-5.3 dialyzer-5.0.1 diameter-2.2.6 edoc-1.2 eldap-1.2.10 erl_docgen-1.3 erl_interface-5.3 et-1.6.5 eunit-2.7.1 ftp-1.1.1 inets-8.0 jinterface-1.13 kernel-8.4.1 megaco-4.4 mnesia-4.21.1 observer-2.12 odbc-2.14 os_mon-2.7.1 parsetools-2.4 public_key-1.13 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13 ssh-4.14.1 stdlib-4.0.1 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.29 :
OTP-25.0.1 : crypto-5.1.1 dialyzer-5.0.1 erts-13.0.1 kernel-8.4.1 mnesia-4.21.1 ssh-4.14.1 ssl-10.8.1 stdlib-4.0.1 # asn1-5.0.19 common_test-1.23 compiler-8.2 debugger-5.3 diameter-2.2.6 edoc-1.2 eldap-1.2.10 erl_docgen-1.3 erl_interface-5.3 et-1.6.5 eunit-2.7.1 ftp-1.1.1 inets-8.0 jinterface-1.13 megaco-4.4 observer-2.12 odbc-2.14 os_mon-2.7.1 parsetools-2.4 public_key-1.13 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.29 :
OTP-25.0 : asn1-5.0.19 common_test-1.23 compiler-8.2 crypto-5.1 debugger-5.3 dialyzer-5.0 diameter-2.2.6 edoc-1.2 erl_docgen-1.3 erl_interface-5.3 erts-13.0 eunit-2.7.1 inets-8.0 jinterface-1.13 kernel-8.4 megaco-4.4 mnesia-4.21 observer-2.12 odbc-2.14 parsetools-2.4 public_key-1.13 runtime_tools-1.19 sasl-4.2 snmp-5.13 ssh-4.14 ssl-10.8 stdlib-4.0 syntax_tools-3.0 tools-3.5.3 wx-2.2 xmerl-1.3.29 # eldap-1.2.10 et-1.6.5 ftp-1.1.1 os_mon-2.7.1 reltool-0.9 tftp-1.0.3 :
+OTP-24.3.4.11 : erts-12.3.2.11 inets-7.5.3.4 ssl-10.7.3.7 # asn1-5.0.18.1 common_test-1.22.1.1 compiler-8.1.1.3 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4.1 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 jinterface-1.12.2 kernel-8.3.2.3 megaco-4.3 mnesia-4.20.4.2 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12.0.3 ssh-4.13.2.2 stdlib-3.17.2.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
OTP-24.3.4.10 : erts-12.3.2.10 inets-7.5.3.3 snmp-5.12.0.3 # asn1-5.0.18.1 common_test-1.22.1.1 compiler-8.1.1.3 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4.1 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 jinterface-1.12.2 kernel-8.3.2.3 megaco-4.3 mnesia-4.20.4.2 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 ssh-4.13.2.2 ssl-10.7.3.6 stdlib-3.17.2.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
OTP-24.3.4.9 : compiler-8.1.1.3 erts-12.3.2.9 inets-7.5.3.2 ssh-4.13.2.2 ssl-10.7.3.6 # asn1-5.0.18.1 common_test-1.22.1.1 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4.1 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 jinterface-1.12.2 kernel-8.3.2.3 megaco-4.3 mnesia-4.20.4.2 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12.0.2 stdlib-3.17.2.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
OTP-24.3.4.8 : erts-12.3.2.8 snmp-5.12.0.2 # asn1-5.0.18.1 common_test-1.22.1.1 compiler-8.1.1.2 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4.1 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 inets-7.5.3.1 jinterface-1.12.2 kernel-8.3.2.3 megaco-4.3 mnesia-4.20.4.2 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 ssh-4.13.2.1 ssl-10.7.3.5 stdlib-3.17.2.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
diff --git a/system/doc/general_info/DEPRECATIONS b/system/doc/general_info/DEPRECATIONS
index 8a9ba8ed77..a576881e5d 100644
--- a/system/doc/general_info/DEPRECATIONS
+++ b/system/doc/general_info/DEPRECATIONS
@@ -22,6 +22,7 @@
#
file:pid2name/1 since=26 remove=27
disk_log:inc_wrap_file/1 since=26 remove=28
+dbg:stop_clear/0 since=26 remove=27
#
# Added in OTP 25.
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index 34e622a67e..6b3ba96b6b 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -1938,6 +1938,20 @@ catch
exit:Reason -> {'EXIT',Reason}
error:Reason:Stk -> {'EXIT',{Reason,Stk}}
end</code>
+
+ <p>Variables bound in the various parts of these expressions have different scopes.
+ Variables bound just after the <c>try</c> keyword are:</p>
+ <list type="bulleted">
+ <item>bound in the <c>of</c> section</item>
+ <item>unsafe in both the <c>catch</c> and <c>after</c> sections, as well as after the whole construct</item>
+ </list>
+ <p>Variables bound in <c>of</c> section are:</p>
+ <list type="bulleted">
+ <item>unbound in the <c>catch</c> section</item>
+ <item>unsafe in both the <c>after</c> section, as well as after the whole construct</item>
+ </list>
+ <p>Variables bound in the <c>catch</c> section are unsafe in the <c>after</c> section, as well as after the whole construct.</p>
+ <p>Variables bound in the <c>after</c> section are unsafe after the whole construct.</p>
</section>
<section>
@@ -2426,4 +2440,3 @@ KeyPattern := ValuePattern &lt;- MapExpression</pre>
* 1:7: syntax error before: '&lt;'</pre>
</section>
</chapter>
-